Hi Martin,
Your last example was brilliant! I have it all working now. In my
resource class I need these injected by Guice:
@Path("whatever")
public class MyResource
{
@Inject
private EntityManager manager;
@Named("something")
private Processor processor;
}
So manager is just a normal injection from Guice while processor is
named. Note that the Inject annotation is Jersey's version, not
Guice's. And now for the code to make this work:
web.xml:
...
<servlet-class>com.whatever.GuiceServlet</servlet-class>
...
public class GuiceServlet extends ServletContainer
{
private static final long serialVersionUID = 1l;
@Override
protected void initiate(ResourceConfig config, WebApplication app)
{
app.initiate(config, new GuiceComponentProvider());
app.addInjectable(new GuiceNamedInjectable());
}
}
public class GuiceComponentProvider implements ComponentProvider
{
private static Injector injector;
public static Injector getInjector()
{
if (injector == null)
injector = Guice.createInjector(new MyModule());
return injector;
}
@Override
public <T> T getInjectableInstance(T instance)
{
return instance;
}
@Override
public <T> T getInstance(Scope scope, Class<T> clazz) throws
InstantiationException,
IllegalAccessException
{
return getInjector().getInstance(clazz);
}
@Override
public <T> T getInstance(Scope scope, Constructor<T> constructor,
Object[] parameters)
throws InstantiationException, IllegalArgumentException,
IllegalAccessException,
InvocationTargetException
{
return getInstance(scope, constructor.getDeclaringClass());
}
@Override
public void inject(Object instance)
{
getInjector().injectMembers(instance);
}
}
public class GuiceNamedInjectable extends Injectable<Named, Object>
{
@Override
public Class<Named> getAnnotationClass()
{
return Named.class;
}
@Override
public Object getInjectableValue(Object object, Field field, Named
annotation)
{
return GuiceComponentProvider.getInjector().getInstance(
Key.get(field.getType(), annotation));
}
}
So the GuiceComponentProvider.getInstance method handles normal
(non-named) injections and GuiceNamedInjectable.getInjectableValue
handles named injections.
I wonder if there is any way to add the Injectable functionality to
ComponentProvider so there would only be one class needed to do both
types of Guice injections? Anyways, this works for now and I'm very
happy - thanks for your help!
Thanks,
Zach
On Sun, May 18, 2008 at 12:21 PM, Martin Grotzke
<martin.grotzke_at_freiheit.com> wrote:
> Hi Zach,
>
> just to mention - I have no clue how guice works. :)
>
> But I'd say that you don't need an extra annotation @MyAnnotation but
> you can refer directly @Named:
>
> @Override
> protected void initiate( ResourceConfig rc, WebApplication wa ) {
> super.initiate( rc, wa );
>
> wa.addInjectable(new Injectable<Named, Object>() {
> @Override
> public Object getInjectableValue(Object o, Field f, Named a)
> Injector injector = ...;
> return injector.getInstance(Key.get(f.getType(),
> Names.named( a.value() ));
> }
>
> @Override
> public Class<Named> getAnnotationClass() {
> return Named.class;
> }
> });
> }
>
> With this you can have fields of different types and your specific
> names, e.g.:
>
>
> @Named("something")
> private Processor processor;
>
> @Named("username")
> private String username;
>
> @Named("password")
> private String password;
>
> I'm not really sure, but AFAICS you also don't need a specific
> ComponentProvider with this.
>
>
> Cheers,
> Martin
>
>
> On Sun, 2008-05-18 at 11:35 -0400, Zach Cox wrote:
>> Hi Martin,
>>
>> Injectable definitely seems useful! So in my use case, I need to
>> inject a named Processor instance which I'd usually do in Guice like
>> this:
>>
>> Where it needs to be injected:
>>
>> @Inject
>> @Named("something")
>> private Processor processor;
>>
>> In my AbstractModule subclass:
>>
>> bind(Processor.class).annotatedWith(Names.named("something")).to(ProcessorImpl.class);
>>
>> So in Jersey would I do something like this?
>>
>> Where it needs to be injected:
>>
>> @MyAnnotation
>> private Processor processor;
>>
>> In my ServletContainer subclass:
>>
>> public class MyServletContainer extends ServletContainer {
>>
>> @Override
>> protected void initiate( ResourceConfig rc, WebApplication wa ) {
>> super.initiate( rc, wa );
>>
>> wa.addInjectable(new Injectable<MyAnnotation, Processor>() {
>> @Override
>> public Processor getInjectableValue(Object o, Field f,
>> MyAnnotation a)
>> Injector injector = ...;
>> return injector.getInstance(Key.get(Processor.class,
>> Names.named("something"));
>> }
>>
>> @Override
>> public Class<MyAnnotation> getAnnotationClass() {
>> return MyAnnotation.class;
>> }
>> });
>> }
>>
>> @Target({FIELD, PARAMETER, CONSTRUCTOR })
>> @Retention(RUNTIME)
>> @Documented
>> public static @interface MyAnnotation {
>>
>> }
>>
>> }
>>
>>
>> Thanks,
>> Zach
>>
>>
>> On Sun, May 18, 2008 at 11:17 AM, Martin Grotzke
>> <martin.grotzke_at_freiheit.com> wrote:
>> > Hi Zach,
>> >
>> > it sounds as if a feature introduced together with the
>> > spring-integration would be useful for you.
>> > I just wrote a short posting about this [1], but I also want to document
>> > these DI-related features in the wiki - still on my TODO-list :)
>> >
>> > Cheers,
>> > Martin
>> >
>> >
>> > [1] http://www.javakaffee.de/blog/2008/05/18/jersey-di-use-custom-annotations-for-dependency-injection-in-your-resource-classes/
>> >
>> >
>> > On Sun, 2008-05-18 at 09:25 -0400, Zach Cox wrote:
>> >> Hi Paul,
>> >>
>> >> Thanks for the pointers! Here's what I've done so far (I'll post code
>> >> once it's all working):
>> >> - GuiceComponentProvider implements ComponentProvider
>> >> - getInstance(Scope, Class<T>) uses Injector.getInstance method to
>> >> create the object
>> >> - inject(Object) uses Injector.injectMembers to inject members of the object
>> >> - GuiceServlet extends ServletContainer
>> >> - initiate(ResourceConfig, WebApplication) creates
>> >> GuiceComponentProvider & passes it to WebApplication.initiate
>> >> - web.xml
>> >> - <servlet-class>com.whatever.GuiceServlet</servlet-class>
>> >>
>> >> With Guice, you can annotate the injected members, which is really
>> >> convenient for commonly used types for which you need different
>> >> instances injected in different places (like Strings).
>> >>
>> >> In some class that needs a username & password injected:
>> >>
>> >> @Inject
>> >> @Named("username")
>> >> private String username;
>> >>
>> >> @Inject
>> >> @Named("password")
>> >> private String password;
>> >>
>> >> In your AbstractModule subclass:
>> >>
>> >> bindConstant().annotatedWith(Names.named("username")).to("scuba");
>> >> bindConstant().annotatedWith(Names.named("password")).to("steve");
>> >>
>> >> I actually need to annotate one of the fields to be injected by
>> >> GuiceComponentProvider similar to the above. Is this possible using
>> >> the ComponentProvider.getInstance(Scope, Class<T>) method? I'm not
>> >> sure how to discover the @Named annotation and pass that info along to
>> >> Guice.
>> >>
>> >> Thanks,
>> >> Zach
>> >>
>> >>
>> >> On Thu, May 15, 2008 at 12:45 PM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>> >> > Hi Zach,
>> >> >
>> >> > Zach Cox wrote:
>> >> >>
>> >> >> I found Christian Rivasseau's great work on Guice + Jersey:
>> >> >>
>> >> >>
>> >> >> http://objectif-naiade.blogspot.com/2007/11/integrating-jersey-with-guice-and.html
>> >> >>
>> >> >> But that code was written back in Nov 2007 and the ResourceProvider
>> >> >> interface is much different now in 0.8. Is there any code around to
>> >> >> easily use Guice to inject field/method parameters in resource classes
>> >> >> in 0.8? Or are there any tutorials/code examples I could study to
>> >> >> create Guice integration in 0.8?
>> >> >>
>> >> >
>> >> > If you are familiar with Guice, perhaps looking at a WebBeans example might
>> >> > help [1].
>> >> >
>> >> > Plus you can look at the Spring code here [2].
>> >> >
>> >> > Things have changed to use the ComponentProvider interface. You can probably
>> >> > hack things together to get things working by just implementing the
>> >> > ComponentProvider.getInstance() method:
>> >> >
>> >> >
>> >> > public static class GuiceComponentProvider
>> >> > implements ComponentProvider {
>> >> >
>> >> > public <T> T getInjectableInstance( T instance ) {
>> >> > return instance;
>> >> > }
>> >> >
>> >> > public SpringComponentProvider(
>> >> > ConfigurableApplicationContext springContext) {
>> >> > this.springContext = springContext;
>> >> > }
>> >> >
>> >> > public <T> T getInstance( Scope scope, Class<T> clazz )
>> >> > throws InstantiationException, IllegalAccessException {
>> >> >
>> >> > // Insert Guice specific code here to get the instance
>> >> > }
>> >> >
>> >> > public <T> T getInstance(Scope scope,
>> >> > Constructor<T> constructor,
>> >> > Object[] parameters)
>> >> > throws InstantiationException, IllegalArgumentException,
>> >> > IllegalAccessException, InvocationTargetException {
>> >> > return getInstance(scope, constructor.getDeclaringClass());
>> >> > }
>> >> >
>> >> > public void inject(Object instance) {
>> >> > }
>> >> > }
>> >> >
>> >> > Paul.
>> >> >
>> >> > [1]
>> >> > http://stephan.reposita.org/archives/2008/02/25/adding-web-beans-jsr-299-to-jersey-for-rest/
>> >> > [2]
>> >> > https://jersey.dev.java.net/source/browse/*checkout*/jersey/trunk/contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringServlet.java?rev=998
>> >> >
>> >> >
>> >> > --
>> >> > | ? + ? = To question
>> >> > ----------------\
>> >> > Paul Sandoz
>> >> > x38109
>> >> > +33-4-76188109
>> >> >
>> >> > ---------------------------------------------------------------------
>> >> > To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> >> > For additional commands, e-mail: users-help_at_jersey.dev.java.net
>> >> >
>> >> >
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> >> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>> >
>> >
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>