Search code examples
javadependency-injectionrepositoryguicecode-injection

Repository-like injected object, initialize safely


I would like to create an object that basically functions as a list, and i will inject it in my services, using Guice

public class MyRepository {
  List<MyInterface> list = new ArrayList<>();

  public void add(MyInterface obj){
    list.add(obj);
  } 

  public List<MyInterface> get(){
    return list;
  }
}

Then i am gonna to be using injection from various points to add elements to this list

public class ObjectA implements MyInterface {
  @Inject
  public ObjectA(MyRepository myRepository){
    myRepository.add(this);
  }
}

My question is, i want to ensure that MyRepository is used in services only after all potential subscribers have been added.

Multibinder is not applicable because i will be needed some specific methods

Is there a way to do that? Thanks


Solution

  • If you're using multibinder you're probably wanting to do something like this? You don't want to use static as it would break the @Inject MyRepository repository; logic downstream.

    Assuming you have your multibinder configured appropriately then your repository should work like this:

    class MyRepository {
       Set<MyInterface> interfaces;
    
       @Inject
       public MyRepository(Set<MyInterface> interfaces) {
          // Here you can do some things like re-applying the interfaces to
          // a TreeSet (for example) if you needed to control priority.
          this.interfaces = interfaces;
       }
    
       public Set<Permissions> getPermissions(final User user) {
          // However you want to iterate through the interfaces
          return interfaces.stream()
                .flatMap(i -> i.getPermissions(user)) // maybe?
                .collect(Collectors.toSet());
       }
    }
    

    You can have:

    • Different methods for iterating the interfaces
    • You can filter the interfaces based on other Interfaces. For example if one MyInterface also extends MyOtherInterface

    If I'm missing something, please update/comment and we can sort it out.