>
> This is almost identical to your example, but instead of injecting 
> *@Named("...") 
> Image* and relying on what would be a new feature, it injects 
> *ProviderOfNamed<T>*, and the desired image is obtained through a call to 
> *provider.get(name)*. The *@Provides* method is essentially the same.
>

you're absolutely correct about this, and I should've been thinking along 
these lines from square one.

This is almost identical to your example, but instead of injecting 
*@Named("...") 
> Image* and relying on what would be a new feature, it injects 
> *ProviderOfNamed<T>*, and the desired image is obtained through a call to 
> *provider.get(name)*. The *@Provides* method is essentially the same.
>

You are correct that it is almost identical --I don't know why I got 
trapped in the mode of thinking that I needed to inject big monolithic 
all-loading classes just to load an image, I can (and should) hive that off 
into nice little interfaces, exactly as you're doing here. This will go a 
long way to achieving my goal.

I still have minor gripes: In this example SomeService should not depend on 
a process to load an image, it should depend on the image. Thanks to guice 
(and java-8) it is not hard to implement that process using a factory (or 
provider) for production and a lambda for testing. But there are problems 
with this approach. I would imagine that serialization of a class 
(SomeService) that had saved a reference to a provider (ProviderOfNamed) 
would be difficult, and also the life cycle of the provider is implied to 
be a one-shot, (ie, the provider gets called once and then garbage 
collected), which is easy to accidentally abuse. 

Anyways, I've made my point, and you've given me some ideas. For now you 
are exactly right, I'll create an interface that is just for loading 
images, and bind it to the monolithic object we already have for production 
and, if I keep the image small enough, I'll be able to do something as 
simple as name -> mock(Image.class); for testing.

-Geoff

On Sunday, October 25, 2015 at 10:26:39 AM UTC-7, Tim Peierls wrote:
>
> On Saturday, October 24, 2015 at 11:43:59 PM UTC-4, Geoff Groos wrote:
>>
>> the benefit is fairly straight forward: you don't have to inject a 
>> `ResourceEnvironment` instance, and we lose a little bit of code 
>> duplication by centralizing the place where the resource-loading flow 
>> starts and finishes. 
>>
>
> I should have used a less "heavy" sounding term than ResourceEnvironment. 
> How about an interface, ProviderOfNamed<T>? Here's my rewrite of your 
> example again, but with the different name:
>
> https://gist.github.com/Tembrel/5662bdecc0d3557debc1 
> <https://www.google.com/url?q=https%3A%2F%2Fgist.github.com%2FTembrel%2F5662bdecc0d3557debc1&sa=D&sntz=1&usg=AFQjCNHcXPgwUce3NVIkpHtJjU5idzzKlA>
>
> This is almost identical to your example, but instead of injecting 
> *@Named("...") 
> Image* and relying on what would be a new feature, it injects 
> *ProviderOfNamed<T>*, and the desired image is obtained through a call to 
> *provider.get(name)*. The *@Provides* method is essentially the same.
>
>  
>
>> That same object is the one that offers the ability to load native code 
>> through JNA, so its a fairly scary object. If it becomes too scary we of 
>> course have the option of hiving that complexity off into a new class, a 
>> `NativeResourceLoader` and the regular `ResourceEnvironment`, but I just 
>> thought the ability to push the actual loading of resources out of a 
>> constructor and into guice would be handy.
>>
>
> I don't think you want to describe it as pushing logic *into *Guice. 
> Better to say that you want to decouple the actual (and common) machinery 
> of loading a resource based on a string name from the places where those 
> resources are used. Both of our examples accomplish that end, but mine does 
> it without needing a new and potentially very complicated enhancement to 
> Guice.
>
>  
>
>> And I would think that this would be a handy feature for deep 
>> configuration: if the type isn't a uniquely identifying feature, the 
>> ability to make runtime decisions about static configuration through 
>> annotations seems really handy and not likely to break much (whose going to 
>> be binding instances of annotations to things?) In my case, a static image 
>> resource can be identified by a path similar to 
>> "/com/ourcompany/whatever/someimage.png". 
>>
>
> I'm not following this. Are you saying that you'd like to do static code 
> analysis so you can do build-time initialization of configuration data 
> structures? I can sort of see an application for this, but I don't think 
> it's worth introducing a new Guice feature for it. I would do something 
> like this:
>
>
> class SomeService {
>
>   static final String IMG_NAME = "/com/whatever/...";
>
>   @Preconfigured(IMG_NAME) final Image img;
>
>   @Inject SomeService(ProviderOfNamed<Image> imgProvider) {
>     img = imgProvider.get(IMG_NAME);
>   }
> }
>
>
> Then a static analysis tool could go through a jar and know from which 
> things need to be "preconfigured", whatever that means.
>
>
> On Sunday, October 18, 2015 at 7:30:06 AM UTC-7, Tim Peierls wrote:
>>>
>>> What benefits would this have over what I imagine your colleagues are 
>>> doing?
>>>
>>> public interface ResourceEnvironment {
>>>   Image getImage(String name);
>>>   // ... other resource-providing methods ...
>>> }
>>>
>>> public class SomeService {
>>>
>>>   private final Image image;
>>>
>>>   @Inject public SomeService(ResourceEnvironment env){
>>>     image = env.getImage("/com/mycompany/myasset.png");
>>>   }
>>>
>>>   //big complex methods doing big complex method things.
>>> }
>>>
>>> //with a module containing 
>>> public class ModuleToDoThat implements Module{
>>>   public void configure(){
>>>     //...
>>>   }
>>>   
>>>   @Provides ResourceEnvironment getResourceEnvironment() {
>>>     return new ResourceEnvironment() {
>>>   @Override public getImage(String name) {
>>> return toImage(getClassLoader().getResource(name));
>>>   }
>>>   Image toImage(URL url) { ... }
>>>   // ... implement other resource-providing methods ...
>>>     };
>>>   }
>>> }
>>>
>>>
>>> On Sun, Oct 18, 2015 at 1:18 AM, Geoff Groos <geoff...@empowerops.com> 
>>> wrote:
>>>
>>>> Hey guys,
>>>>
>>>> So it's occurred to me that a number of classes in our codebase are 
>>>> injecting a so called 'ResourceEnvironment' so they can use it to retrieve 
>>>> a static image from whiten our deployed jar. This got me wondering if I 
>>>> could achieve something as slick as injecting the image directly with 
>>>> guice:
>>>>
>>>> public class SomeService{
>>>>
>>>>   private final Image image;
>>>>
>>>>   @Inject
>>>>   public SomeService(@Named("/com/mycompany/myasset.png") myAssetImage
>>>> ){
>>>>     image = myAssetImage;
>>>>   }
>>>>
>>>>   //big complex methods doing big complex method things.
>>>> }
>>>>
>>>> //with a module containing 
>>>> public class ModuleToDoThat implements Module{
>>>>   public void configure(){
>>>>     //...
>>>>   }
>>>>   
>>>>   @Provides Image getImageWithName(Named name){
>>>>     return getClassLoader().getResource(name.value());
>>>>   }
>>>> }
>>>>
>>>> This would actually reduce a fair bit of code on our code base; using 
>>>> annotations to pass meta-data about the specific instance that's needed 
>>>> *at 
>>>> runtime* would be a really cool feather for guice's cap. 
>>>>
>>>> AFAIK the feature I'm requesting is binding annotations to be 
>>>> whitelisted (along with the calling Injector) as things that you can 
>>>> request without providing an explicit configuration path for them. A 
>>>> little 
>>>> less obtusely: with the injector you don't need to tell guice how to 
>>>> provide a provider method with an injector, it just assumes the injector 
>>>> you're looking for is the one doing the provide-ing. I would ask that 
>>>> binding annotations be given the same 'scope', such that any binding 
>>>> annotations used would be automatically wired to that provider method (and 
>>>> if they don't exist, the provider methods eligibility for provision 
>>>> removed). 
>>>>
>>>> Needless to say this is a fair bit of rope to hang yourself with, in 
>>>> the event that you need to start passing more information than is 
>>>> available 
>>>> at annotation-writing-time, some developers (myself included) might try to 
>>>> ham-fist some things into static scope so that they can be used by the 
>>>> annotation. That said, I think the benefit outweighs the cost; it would be 
>>>> really slick and cut 50 lines of cruft off my codebase. 
>>>>
>>>> I'm *fairly* certain I could hack something together with provision 
>>>> listener and a stack (probably static), but rather than go down that road 
>>>> I 
>>>> figured I should post this as a request-for-help and/or a feature request 
>>>> here first.
>>>>
>>>> Is there a way to do this without using the SPI that would give me the 
>>>> same effect? If I was to try to do it myself with a stack and a provision 
>>>> listener, would it be as hard as I think it is? Is this something I should 
>>>> request a little more formally (by creating a github issue)?
>>>>
>>>> cheers,
>>>>
>>>> -Geoff
>>>>
>>>>
>>>> -- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "google-guice" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to google-guice...@googlegroups.com.
>>>> To post to this group, send email to google...@googlegroups.com.
>>>> Visit this group at http://groups.google.com/group/google-guice.
>>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/google-guice/882e5b98-a32a-4f5a-a47f-02b4fc8d117b%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/google-guice/882e5b98-a32a-4f5a-a47f-02b4fc8d117b%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-guice+unsubscr...@googlegroups.com.
To post to this group, send email to google-guice@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/google-guice/b2f21aaf-0b42-491e-bdf1-3e6ceb24d953%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to