progress bars on guice get-instance call

39 views
Skip to first unread message

Geoff Groos

unread,
May 29, 2015, 2:31:03 PM5/29/15
to google...@googlegroups.com
Hey guys,

I'm wondering about the best way to go about getting a progress bar on the resolution of guice things.

Rougly speaking, if I have a dependency tree with

RootItem
   -> 1-to-1 instance-of Dependency-1,
   -> 1-to-1 instance-of Dependency-2
        -> 1-to-1 instance-of Grand-Child-Dep-2
   -> 1-to-1 instance-of Dependency-3
        -> 1-to-many instance-of GrandChildDep-3


and dependency-3's ctor looks like this:

public Dep3{
   
@Inject
   
public Dep3(List<Model> models){
       
for(Model model : models){
           
GrandChildDep3 deepdep = guiceProvidedFactory.createFor(model);
           
//...
       
}
   
}
}

What would be the best process to make a progress bar for such a system?

I've got an object that I use for serialization that uses a stack to track progress. In this way we can have a tree like structure of tasks, so long as we can get the number of child tasks under any given task.

public NotifyingSerializer extends RealSerializer{

   
ProgressBarUpdater updater;

   
@Override
   
public marshal(...){
        updater
.pushNewTask(/*speculate, or use meta about the model, to guess at how many child-tasks this one has*/ 45);
       
super.marshall(...);
        updater
.popTask();
   
}

   
//similar for unmarshal
}

I'd like to use this same object for guice tasks.

The best I've been able to do so far is putting the pushTask call in a SPI ProvisionListener, and the corresponding popTask at the end of each constructor.

eg:

binder
().bindListener(
       
new AbstractMatcher<Binding<?>>() {
           
Set<Class> types = ImmutableSet.of(
                   
(Class) RootItem.class, Dependency1.class,
                   
Dependency2.class, Dependency3.class,
                   
GrandChildDep2.class, GrandChildDep3.class);
           
@Override public boolean matches(Binding<?> binding) {
               
return types.contains(binding.getKey().getTypeLiteral().getRawType());
           
}
       
},
       
new ProvisionListener(){
           
Class provisionedType = provision.getBinding().getKey().getTypeLiteral().getRawType();
           
//do a filter to find out if this provision is just because of a factory call
           
if(provision.getDependenyChain().stream().filter(dep -> dep.getDependency().getKey().getTypeLiteral().getRawType().equals(provisionedTyped)).size() == 1){

                updater
.pushTask(/*use static knowledge to figure out how many subtasks this dep will have*/);

           
}
       
}
);

//...

public Class RootItem{

   
@Inject
   
public RootItem(Dependency1 dep1, Dependency2 dep2, Dependency3 dep3,
                   
/*other misc items*/,
                   
ProgressBarUpdater updater){
   
       
//... ctor-things
        updater
.popTask();
   
}

}


This is not a great solution because
  • it involves modifying a lot of production code to include the popTask line,
  • In the event that the object is resolved without a progress-watching-provision-listener (IE, a component uses guice to resolve the component but doesnt include the provision listener that gives us the progress bars), there will be a popTask call with no prior pushTask call. I could handle this case, but it wouldn't be nice.

What I would really like is one of the following:

  • an SPI object that would allow me to get something like onProvisionEnter and onProvisionExit
  • a wrapper Provisioner for all provisioners, so it could contain similar code to whats in my above serializer-wrapper


Is there something I'm missing? Is there an existing elegant way to, from withen guice, get a piece of code executed when a component has been constructed?

Thanks for any help,


-Geoff

Sam Berlin

unread,
May 29, 2015, 2:36:20 PM5/29/15
to google...@googlegroups.com
You can call provisionInvocation.provision() to manually do the provision.  ProvisionListener lets you hook into the entire provision lifecycle -- if you don't call provision() manually, Guice will do it for you.  You can also call it manually and do stuff before & after the provision.  (Provision == creation of the object & injection of its dependents.)

 sam

--
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/548d5336-e0a2-409b-b16f-e657ff688782%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages