users@jersey.java.net

Re: [Jersey] Newbie question: How do I inject objects into resources

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 24 Mar 2009 09:10:42 +0100

Hi Ian,

You can use ResourceConfig [1] if you wish:

   @Context ResourceConfig rc;

   ...

   rc.getProperties().put("dbConn", dbConn);

   ...

   (Connection)rc.getProperty("dbConn");

which are per-Web application properties.


Or you can do the same with HttpContext [2]:

   @Context HttpContext hc;

   ...

   hc.getProperties().put("dbConn", dbConn);

   ...

   (Connection)cc.getProperties().get("dbConn");

which are per-request properties.

Or you could use the servlet context or request attributes if you
want to be specific to servlet.


The injection mechanism is as complex as it needs to be to ensure
integration with IoC frameworks, as Craig says, in addition to
correct IoC support when injection artifacts onto other artifacts
while ensuring correct scope matching, in addition to supporting all
the @*Param types which are special cases, but yet it is still
possible to support your own injection of those and override the
default.

The advantage of utilizing an injection provider is that once
implemented injection will work under many scenarios (constructor,
field, method, setter, on both providers and resource classes),
without requiring casting and lookup using a string parameter.

There are a couple of helper classes to simplify the construction in
certain cases, it very much depends on what you want to inject and
what the life-cycle is. For helper classes see
SingletonTypeInjectableProvider [3] and
PerRequestTypeInjectableProvider [4].

If you want to support the injection of a singleton value using
@Context you can do:

@Provider
public class MyProvider extend
SingletonTypeInjectableProvider<Context, MyType> {
     public MyProvider() {
         MyType t = ....
         super(MyType.class, t);
     }
}

For a more advanced example of injecting EJBs see the attachment in
the following:

http://markmail.org/search/?q=net.java.dev.jersey.users+type%3Ausers
+EJB#query:net.java.dev.jersey.users%20type%3Ausers%20EJB%20order%
3Adate-backward+page:1+mid:catyvvrocdk2h4gx+state:results

Hope this helps,
Paul.

[1 https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/
jersey-1.0.2/api/jersey/com/sun/jersey/api/core/ResourceConfig.html
[2] https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/
jersey-1.0.2/api/jersey/com/sun/jersey/api/core/HttpContext.html
[3] https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/
jersey-1.0.2/api/jersey/com/sun/jersey/spi/inject/
SingletonTypeInjectableProvider.html
[4] https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/
jersey-1.0.2/api/jersey/com/sun/jersey/spi/inject/
PerRequestTypeInjectableProvider.html

On Mar 24, 2009, at 7:36 AM, Ian Clarke wrote:

> Thanks Craig,
>
> I've got to say though that this seems exceedingly complicated for
> something that one might imagine you'd need to do in every non-
> trivial Jersey app.
>
> By way of comparison, in the Restlet framework, you just do
> something like:
> router.getContext().getAttributes().put("databaseConn", dbConn);
>
>
>
> You can then access it within the resource with something like:
> Connection conn = (Connection) context.getAttributes().get("dbConn");
>
> Why is this so much more complicated with Jersey?
>
> I switched to Jersey from Restlet because on the surface it looked
> simpler and more elegant, I regret to say that I'm now having
> doubts about this decision :-/
>
> (I'm not attacking those who've been kind enough to respond to my
> questions, I'm grateful for that - I'm just hoping that someone can
> convince me that either this isn't as complicated as it appears, or
> that there is a good justification for the complexity).
>
> Ian.
>
> On Mon, Mar 23, 2009 at 9:48 PM, Craig McClanahan
> <Craig.McClanahan_at_sun.com> wrote:
> Ian Clarke wrote:
>>
>> Thanks for that.
>>
>> Can you point me to a simple example of using the Injectable
>> annotations?
> One example is in the contribs/jersey-multipart project, where I
> wanted to be able to inject an instance of
> "com.sun.jersey.multipart.MultiPartConfig" into my resource
> classes. I wrote a provider for this in class
> "com.sun.jersey.multipart.impl.MultiPartConfigProvider" and
> configured it with a "src/main/java/META-INF/services/
> com.sun.jersey.multipart.impl.MultiPartImplProvider" file that has
> to end up in META-INF/services in your WEB-INF/classes directory or
> inside a jar in WEB-INF/lib.
>
> This lets me inject resources (using @Context, as you correctly
> surmised) into classes like
> com.sun.jersey.multipart.impl.MultiPartReader.
>
> In my case, I declared that MultiPartConfig was a singleton, and
> created it in the getInjectable() method (which will only get
> called once because of the scope value).
>
> For dealing with JDBC, here's what I would suggest:
>
> * Configure a JDBC DataSource in the JNDI environment for your
> application.
>
> * In the getInjectable() method of your provider, do a JNDI lookup
> to get the
> DataSource instance.
>
> * Make the class of the injected object have a getDataSource()
> method on it
> that returns this data source instance.
>
> * In a resource method that received the injected object, have it call
> getDataSource().getConnection() on the injected object to get a
> connection,
> and then call connection.close() when you are through to return
> that connection
> to the data source's pool. Be sure you do this close even if an
> exception
> gets thrown along the way.
>
> The last step ensures that you won't have two (or more)
> simultaneous requests fighting over the same JDBC Connection
> instance, which is not allowed.
>
> Craig
>
>>
>> Ian.
>>
>> On Mon, Mar 23, 2009 at 7:19 PM, Erdinc Yilmazel
>> <erdinc_at_yilmazel.com> wrote:
>> Hi,
>>
>> You may write your own Injectables and InjectableProviders for
>> injecting custom objects. You may even define your own annotations
>> for
>> that. See :
>>
>> com.sun.jersey.spi.inject.Injectable
>> com.sun.jersey.spi.inject.InjectableProvider
>> com.sun.jersey.spi.inject.Inject
>>
>> After writing and InjectableProvider you must annotate it with
>> @Provider annotation to make Jersey aware of that class.
>>
>> The @Context annotation has also its InjectableProvider.
>>
>> The other choice is using a IOC framework like google guice. Support
>> for google guice may be bundled with the upcoming 1.0.3 version of
>> Jersey, but you can find an example code in jersey subversion
>> repository.
>>
>> Erdinc
>>
>> On Mon, Mar 23, 2009 at 11:33 PM, Ian Clarke
>> <ian.clarke_at_gmail.com> wrote:
>> > I have an object, lets say a SQL connection, that I want my
>> Jersey resource
>> > classes to have access to, but I don't want to make the SQL
>> connection
>> > static (because some day there may be more than one of them).
>> >
>> > How do I inject an object like this into a resource class so
>> that it can use
>> > it? For that matter, how do I tell resource classes about any
>> objects
>> > without making them available statically?
>> >
>> > I have a feeling it may be something to do with the @Context
>> annotation, but
>> > I haven't been able to find clear documentation on this.
>> >
>> > Any help would be appreciated,
>> >
>> > Ian.
>> >
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>>
>>
>>
>> --
>> Ian Clarke
>> CEO, Uprizer Labs
>> Email: ian_at_uprizer.com
>> Ph: +1 512 422 3588
>> Fax: +1 512 276 6674
>
>
>
>
> --
> Ian Clarke
> CEO, Uprizer Labs
> Email: ian_at_uprizer.com
> Ph: +1 512 422 3588
> Fax: +1 512 276 6674