Oh and I should mention that I haven't got any static code analysis tools 
along these lines.

All I'm suggesting is that there are other use-cases for this besides 
loading images, DB connections come to mind although there you might want 
all the typical try-finally ritual typically associated with db connections.

In our particular case we have a graph that we configure. If I could 
specify paths into that graph for injection it would save me a lot of test 
setup headache. Consider:

GraphAnalyzingThing(Graph graph){
  nodesOfInterest = graph.getRoot().resolve("A").flatMap(node -> node.
resovle("B"));
}

vs

GraphAnalyzingThing(@Named("/ANodes/BNodes") List<Node> nodes){
  thingsOfInterest = nodes;
}

//with a provider:
@Provides List<Node> getNodesForPath(Graph graph, Named path){
  List<String> traversal = path.split("/");
  List<node> nodes = { graph.getRoot() };
  for(String pathSection : traversal){
    nodes = nodes.flatMap(node -> node.resolve(pathSection));
  }
  return nodes;
}


The latter is a lot easier to create from a testing environment, and it 
allows us to centralize some of that traversal logic.

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
>
> 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/a8d21f0a-798a-4a72-a2fc-4764a8177ec4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to