Reputation: 3281
Trying to get started with Guice, and struggling to see how my use-case fits in.
I have a command-line application, which takes several optional parameters.
Let's say I've got the tool shows a customer's orders, for example
order-tool display --customerId 123
This shows all the orders owned by customer with ID 123. Now, the user can also specify a user's name:
order-tool display --customerName "Bob Smith"
BUT the interface to query for orders relies on customer IDs. Thus, we need to map from a customer name to a customer ID. To do this, we need a connection to the customer API. Thus, the user has to specify:
order-tool display --customerName "Bob Smith" --customerApi "http://localhost:8080/customer"
When starting the application, I want to parse all the arguments. In the case where --customerApi
is specified, I want to place a CustomerApi singleton in my IoC context - which is parameterized by the CLI arg with the API URL.
Then, when the code runs to display a customer by name - it asks the context if it has a CustomerApi singleton. If it doesn't it throws an exception, telling the CLI user that they need to specify --customerApi
if they want to use --customerName
. However, if one has been created - then it simply retrieves it from the IoC context.
Upvotes: 0
Views: 94
Reputation: 95764
It sounds like "optionally creating a singleton" isn't exactly what you're trying to do here. I mean, it is, but that's as simple as:
if (args.hasCustomerApi()) {
bind(CustomerApi.class).toInstance(new CustomerApi(args.getCustomerApi()));
}
To allow for optional bindings, you will probably need to annotate their use with @Nullable
.
I think your real question is how to structure an application so that you can partially configure it, use the configuration to read and validate some command-line flags, then use the flags to finish configuring your application. I think the best way to do that is with a child injector.
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AModule(), new BModule(), ...);
Arguments arguments = injector.getInstance(ArgParser.class).parse(args);
validateArguments(arguments); // throw if required arguments are missing
Injector childInjector =
injector.createChildInjector(new ArgsModule(arguments));
childInjector.getInstance(Application.class).run();
}
Child injectors are just like normal injectors that defer to a parent if they don't contain the given bindings themselves. You can also read documents on how Guice resolves bindings.
Upvotes: 1