Guice: inject an ArrayList of strings

I am trying to inject ArrayList

from String

using Guice. I want to show a panel with many RadioButtons (for example) where the user can select some services to activate.

Once selected, I would like to get all the names of the selected services and add them to the list, and also insert this list to the manager responsible for creating the services. Here's an example:

public class UIProviderModule extends ProviderServiceModule {
    private ArrayList<String> requestedServices;

    public UIProviderModule(ArrayList<String> requestedServices) {
        this.requestedServices = requestedServices;
    }

    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named(Constants.REQ_SERVICES)).to(requestedServices);
        bind(IParser.class).to(UIParser.class);
        super.configure();
    }

}

      

I have seen many posts about Multibindings as well as Providers, but I didn’t understand how it could help me. I just want to get the names as I am not working with classes that need to be bound to an interface. Did I miss something?

Note. I know this may not be a very good way to use Guice, because I am passing the list to the associated Module

.

+3


source to share


2 answers


I think you don't understand how modules are supposed to work.

Modules do not create objects, modules define rules for how objects can be created when needed.

The reason MapBinder helps is that you define all the services in the radio button list, and then use the entered map to activate the services you need.

Here's some code to illustrate what I mean:



public class ServiceModule extends AbstractModule {
  protected void configure() {
    MapBinder<String, Service> mapbinder
        = MapBinder.newMapBinder(binder(), String.class, Service.class);
    mapbinder.addBinding("service1").to(Service1.class).in(Singleton.class);
    mapbinder.addBinding("service2").to(Service2.class);
    // Define ALL the services here, not just the ones being used.
    // You could also look this up from a ClassLoader or read from a configuration file if you want
  }
}

      

Then inject MapBinder into a class ServiceManager

- not a module:

public class ServiceManager {
  private final Map<String, Service> serviceMap;

  @Inject
  public ServiceManager(Map<String, Service) serviceMap) {
    this.serviceMap = serviceMap;
  }

  // This is just one way to do it. It depends on how your UI works
  public void startAll(List<String> serviceList) {
    for(String serviceName : serviceList) {
      serviceMap.get(serviceName).start();
    }
  }
}

      

+2


source


This is easy to do with Guice:

bind(new TypeLiteral<List<String>>() {})
    .annotatedWith(Names.named(Constants.REQ_SERVICES))
    .toInstance(requestedServices);

      

Note that for binding List<String>

without Java erasing generics, you are creating a short-lived anonymous inner type (a subclass of TypeLiteral with an empty body {}

). You are also using toInstance

.

There is nothing wrong with a module accepting parameters that are used to bind, and I prefer to do this with Multibindings, where all bindings are easily collected in one place.

Note, the variable ArrayList<String>

you are accepting is changed, so if you enter it in more than one place, one user can change the list forever for everyone else. It might make sense to use Guava ImmutableList.copyOf(list)

or Collections.unmodifiableList(list)

(although the latter will still allow the list to be changed if the module creator later changes the passed list).




Regarding your proposed application lifecycle, remember that Guice bindings should remain more or less constant after the injector is created. The life cycle you describe can make sense in several ways:

  • Show your dialog without Guice, then create an Injector with the parameters selected
  • Fill in your List<String>

    all parameters, show the dialog and then go through the list
  • Fill in yours List<String>

    with all options, show a dialog and then create a child injector containing a list of selected options.

All of this, however, is possible depending on how much you want the complete list and the selected list to be in your application.

+5


source







All Articles