Is the @Singleton scope based on the instance of the Injector being used?

I have two classes that aren't getting injected.   One is a static factory
class (ThreadResourceFactory).  The other is a class that the factory
instantiates for me (ThreadResource).

In my TestNG @BeforeClass method, I call ThreadResourceFactory.get() to
retrieve an instance of ThreadResource for the current TestNG test thread.

Since I couldn't figure out a way to retrieve the injector previously
created by TestNG, I did the following in the ThreadResource constructor:

  Guice.createInjector(new MyModule()).injectMembers(this);

This works sort of, but because I create another injector, it seems to be
managing another set of @Singletons for that new Injector instance.

I'm sure there is a better way to do this, I am just unsure how.  Any
suggestions?

On Fri, Oct 28, 2011 at 11:51 AM, Stuart McCulloch <[email protected]>wrote:

> On 28 Oct 2011, at 18:43, Jeff wrote:
>
> Thanks for the great info and helping me work things out.  The fog is
> clearing.
>
> Since my language provider depends on the environment, is it kosher to do
> something like:
>
>   @Provides *@Named("ENV")* @Singleton
>   public Properties EnvironmentProvider() {
>     //setup env
>     return env;
>   }
>
>   @Provides @Named("LANG") @Singleton *@Inject*
>
> ^ you shouldn't need @Inject here since every parameter in a @Provides
> method will always be injected
>
>   public Properties LanguageProvider*(@Named("ENV")* Properties env) {
>     //load language files based on lang setting in env
>     return lang;
>   }
>
> And if I mark these as @Singleton, am I the one that needs to store and
> manage the instance or does Guice cache the object returned for lang and
> env and never call this method directly again?
>
>
> Guice will apply the scoping around the @Provides method, so you don't
> need cache the result yourself
>
> On Fri, Oct 28, 2011 at 6:32 AM, Stuart McCulloch <[email protected]>wrote:
>
>> On 27 Oct 2011, at 21:12, Jeff wrote:
>>
>> The classes containing the injected fields are TestNG test classes.  I am
>> creating the Injector using the ServiceLoader mechanism within a class that
>> implements org.testng.ISuiteListener.  TestNG automatically picks up and
>> runs the onStart() method before doing anything else and I call
>> createInjector() there.
>>
>> Though, I think I just realized my problem (besides trying to learn/use
>> Guice from within another framework I'm also just learning).
>>
>> The key bit I had not grasped previously was that for Guice/@Inject to
>> work, object instantiation must be done directly by Guice
>> (Injector.getInstance()), at least for the root node of the object graph (I
>> think).
>>
>> Since TestNG instantiates classes without Guice by default, it was just
>> creating normal instances and the @Inject annotations weren't getting
>> processed.
>>
>> TestNG does support Guice via @Test(guiceModule = MyModule.class)annotation, 
>> but I wanted to avoid the need to put this on EVERY test class
>> and thought I could insert my Modules/Providers and enable my custom
>> bindings to work globally.
>>
>> I'm still playing with my code, but I feel like I'm on the right track.
>> Can anyone confirm or help me understand if there is a different way?
>>
>>
>> Yes, either the root of the object graph needs to be instantiated by
>> Guice or you need to use injectMembers(...) to inject an existing instance
>> (in which case you can't use constructor injection in that particular
>> class). Of course one benefit of putting @Test(guiceModule=...) on each
>> test class (or @Guice in the latest version:
>> http://testng.org/doc/documentation-main.html#guice-dependency-injection)
>> is that it documents that you're using dependency injection for that test,
>> and with modern IDEs it's not too hard to add this automatically or use a
>> template. Also note the latest release of TestNG supports module factories
>> so you could use the same factory across all your tests:
>> http://testng.org/javadocs/org/testng/IModuleFactory.html
>>
>> Thanks!!
>>
>> On Thu, Oct 27, 2011 at 5:40 AM, Stuart McCulloch <[email protected]>wrote:
>>
>>> On 27 Oct 2011, at 06:14, Jeff wrote:
>>>
>>> I want to do something like:
>>>
>>> @Inject @Named("conf")
>>> Properties config;
>>>
>>> @Inject @Named("lang")
>>> Properties language;
>>>
>>> Where these objects are singletons initialized once at runtime with
>>> environment-specific information.
>>>
>>> I've tried various things and none result in my Provider or @Provides
>>> methods getting called.  Here is a trimmed down version of my code using a
>>> Provider class:
>>>
>>> *MyModule.java:*
>>>
>>> public class SeleniumInjectionModule extends AbstractModule {
>>>   @Override
>>>   protected void configure() {
>>>
>>> bind(Properties.class).annotatedWith(Names.named("conf")).toProvider(ConfigProvider.class);
>>>
>>> bind(Properties.class).annotatedWith(Names.named("lang")).toProvider(LanguageProvider.class);
>>>
>>>   }
>>> }
>>>
>>>  *ConfigProvider.java:*
>>>
>>> @Singleton
>>> public class ConfigProvider implements Provider<Properties> {
>>>   private final Properties config = new Properties();
>>>
>>>   public ConfigProvider() {
>>>     //Load properties file based on 'config' system property value set
>>> in Maven profile
>>>     ...
>>>     config.load(...);
>>>     ...
>>>   }
>>>   @Override
>>>   public Properties get() {
>>>     return config;
>>>   }
>>> }
>>>
>>>
>>> *LanguageProvider.java:*
>>>
>>> @Singleton
>>> public class LanguageProvider implements Provider<Properties> {
>>>   private final Properties lang = new Properties();
>>>
>>>   public LanguageProvider() {
>>>     //Load properties file based on 'language' system property value set
>>> in Maven profile
>>>     ...
>>>     lang.load(...);
>>>     ...
>>>   }
>>>   @Override
>>>   public Properties get() {
>>>     return lang;
>>>   }
>>> }
>>>
>>> * In my Global Init code:*
>>>     Guice.createInjector(new MyModule());
>>>
>>> What am I missing?
>>>
>>>
>>> Where's the class containing the injected config/language fields
>>> mentioned in the start of this email?
>>>
>>> Assuming that class is called Foo then you need to use
>>> injector.getInstance(Foo.class) - or injector.injectMembers(myFoo) if you
>>> already have an instance of Foo - to start the injection process and inject
>>> those fields. Note that you don't need to do this for everything, just the
>>> class at the beginning of the injection graph to kick things off.
>>>
>>> --
>>> Jeff Vincent
>>> [email protected]
>>> See my LinkedIn profile at:
>>> http://www.linkedin.com/in/rjeffreyvincent
>>> I ♥ DropBox <http://db.tt/9O6LfBX> !!
>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "google-guice" group.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected].
>>> For more options, visit this group at
>>> http://groups.google.com/group/google-guice?hl=en.
>>>
>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "google-guice" group.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected].
>>> For more options, visit this group at
>>> http://groups.google.com/group/google-guice?hl=en.
>>>
>>
>>
>>
>> --
>> Jeff Vincent
>> [email protected]
>> See my LinkedIn profile at:
>> http://www.linkedin.com/in/rjeffreyvincent
>> I ♥ DropBox <http://db.tt/9O6LfBX> !!
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "google-guice" group.
>> To post to this group, send email to [email protected].
>> To unsubscribe from this group, send email to
>> [email protected].
>> For more options, visit this group at
>> http://groups.google.com/group/google-guice?hl=en.
>>
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "google-guice" group.
>> To post to this group, send email to [email protected].
>> To unsubscribe from this group, send email to
>> [email protected].
>> For more options, visit this group at
>> http://groups.google.com/group/google-guice?hl=en.
>>
>
>
>
> --
> Jeff Vincent
> [email protected]
> See my LinkedIn profile at:
> http://www.linkedin.com/in/rjeffreyvincent
> I ♥ DropBox <http://db.tt/9O6LfBX> !!
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>
>
>  --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>



-- 
Jeff Vincent
[email protected]
See my LinkedIn profile at:
http://www.linkedin.com/in/rjeffreyvincent
I ♥ DropBox <http://db.tt/9O6LfBX> !!

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to