How to inject an object that takes parameters from the command line

1,603 views
Skip to first unread message

Maatary Okouya

unread,
Nov 15, 2013, 9:21:03 PM11/15/13
to google...@googlegroups.com
I have an object in my application that need to be created with parameter from the command line. 

E.g. I have the object Infrastructure service which is a singleton object. When i need to create it, i have to supply it with a concurrent hashmap and paramters either coming from the the command line or the GUI. The hasmap is provided by the Gui, it shares it with the infrastructure. 


I was wondering what would be the best approach for such case. The immediate approach i have in mind, is a factory to which those parameter are passed, and will be used to create the infrastructure let say from the Gui. 


Any suggestion, am i seeing the problem the wrong way ? Is guice useful in that case, if yes how. 


Many thanks, 

Maatary

Cédric Beust ♔

unread,
Nov 15, 2013, 10:43:06 PM11/15/13
to google...@googlegroups.com

I suggest using a provider and the awesome (obviously) JCommander library.

  class Main {
    private Arg arg = new Arg();

   public static void main(String[] args) throws Exception {
    class Arg {
      @Parameter(names = "-long")
      public long l;
    }

    new JCommander(arg).parse("-lon", "32");

  }

   @Provider
    public Arg getArg() {
      return arg;
    }
}

then simply

@Inject
private Arg arg;
-- 
Cédric



-- 
Cédric



--
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.
For more options, visit https://groups.google.com/groups/opt_out.

Christian Gruber

unread,
Nov 16, 2013, 12:11:28 AM11/16/13
to google...@googlegroups.com
And the awesome (obviously) jcommander-guice which lets you bind
jcommander commander objects by generating a module that lets JCommander
do its magic, and inject all the values you need.

c.

On 15 Nov 2013, at 19:43, Cédric Beust ♔ wrote:

> I suggest using a provider and the awesome (obviously) JCommander
> library<http://jcommander.org>
> .
>
> class Main {
> private Arg arg = new Arg();
>
> public static void main(String[] args) throws Exception {
> class Arg {
> @Parameter(names = "-long")
> public long l;
> }
>
> new JCommander(arg).parse("-lon", "32");
>
> }
>
> @Provider
> public Arg getArg() {
> return arg;
> }
> }
>
> then simply
>
> @Injectprivate Arg arg;
Christian Gruber :: Google, Inc. :: Java Core Libraries :: Dependency
Injection
email: cgr...@google.com :::: mobile: +1 (646) 807-9839

Maatary Okouya

unread,
Nov 16, 2013, 12:17:06 AM11/16/13
to google...@googlegroups.com, ced...@beust.com
Many thanks for your answer, appreciated. 

Although i might have forgot to mention that i'm new to guice and what you wrote does not make much sense in my body of knowledge. 

I personally come up with a solution in the mean time that i do not like so much but still work. I use the assisted inject framework. 

I saw that this is what is recommended because with provider you can only set information that you know in advance, not things that you get at runtime. In the faq of google guice they seem to recommand the use of assisted inject as well. But i find it so cumbersome. The only advantage is that the factory is generated for you. It feels like an over kills

With respect to your exemple, please do you mind assisting me a bit further by connecting the dots please: I don't see any provider created, the corresponding module that will contain it, how you will initialize the module and call for your instance and etc.... 

Maatary Okouya

unread,
Nov 16, 2013, 12:22:59 AM11/16/13
to google...@googlegroups.com
I don't see any provider here. From the documentation that i red you have to implement the provider interface

Cédric Beust ♔

unread,
Nov 16, 2013, 12:25:31 AM11/16/13
to google...@googlegroups.com
On Fri, Nov 15, 2013 at 9:11 PM, Christian Gruber <cgr...@google.com> wrote:
And the awesome (obviously) jcommander-guice which lets you bind jcommander commander objects by generating a module that lets JCommander do its magic, and inject all the values you need.

How could I not mention the awesomer jcommander-guice, my deepest apologies, Christian.

-- 
Cédric

Christian Gruber

unread,
Nov 16, 2013, 12:27:37 AM11/16/13
to google...@googlegroups.com, ced...@beust.com
You can check this project out - it lists a specific adaptation of
JCommander to Guice. The read me has most of the instructions here:
https://github.com/israfil/jcommander-inject/tree/master/guice

A quit summary is:

You create your Parameters object, say:

class Arg {
@Parameter(names = "-long")
public Long l;
}

And then you can call

Module m =
JCommanderModuleBuilder.bindParameters(Arg.class).withArguments(args).build();

then create your injector using that module. You can then inject your
classes either by directly depending on Arg, or by @Named typed
arguments, like

class MyClass {
@Inject MyClass(@Named("long") Long long) {

}
}

The module builder will create a module which binds all the arguments
into named bindings, which you can inject in your classes

JCommander also uses Guice's custom injection annotation approach, but I
find that a little cumbersome, so I whipped up this. Either way.

cheers,
Christian.


On 15 Nov 2013, at 21:17, Maatary Okouya wrote:

> Many thanks for your answer, appreciated.
>
> Although i might have forgot to mention that i'm new to guice and what
> you
> wrote does not make much sense in my body of knowledge.
>
> I personally come up with a solution in the mean time that i do not
> like so
> much but still work. I use the assisted inject framework.
>
> I saw that this is what is recommended because with provider you can
> only
> set information that you know in advance, not things that you get at
> runtime. In the faq of google guice they seem to recommand the use of
> assisted inject as well. But i find it so cumbersome. The only
> advantage is
> that the factory is generated for you. It feels like an over kills
>
> With respect to your exemple, please do you mind assisting me a bit
> further
> by connecting the dots please: I don't see any provider created, the
> corresponding module that will contain it, how you will initialize the
> module and call for your instance and etc....
>
>
>
>
>
> On Saturday, November 16, 2013 4:43:06 AM UTC+1, Cédric Beust ♔
> wrote:
>>
>> I suggest using a provider and the awesome (obviously) JCommander
>> library<http://jcommander.org>
>> .
>>
>> class Main {
>> private Arg arg = new Arg();
>>
>> public static void main(String[] args) throws Exception {
>> class Arg {
>> @Parameter(names = "-long")
>> public long l;
>> }
>>
>> new JCommander(arg).parse("-lon", "32");
>>
>> }
>>
>> @Provider
>> public Arg getArg() {
>> return arg;
>> }
>> }
>>
>> then simply
>>
>> @Injectprivate Arg arg;
>>
>> --
>> Cédric
>>
>>
>>
>> --
>> Cédric
>>
>>
>>
>> On Fri, Nov 15, 2013 at 6:21 PM, Maatary Okouya
>> <maatar...@gmail.com<javascript:>
>>> email to google-guice...@googlegroups.com <javascript:>.
>>> To post to this group, send email to
>>> google...@googlegroups.com<javascript:>
>>> .
>>> Visit this group at http://groups.google.com/group/google-guice.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>
>>
>
> --
> 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.
> For more options, visit https://groups.google.com/groups/opt_out.


Christian Gruber

unread,
Nov 16, 2013, 12:27:55 AM11/16/13
to google...@googlegroups.com
;)

Maatary Okouya

unread,
Nov 16, 2013, 1:01:28 AM11/16/13
to google...@googlegroups.com
Very interesting indeed. Many thanks, I'll dig in into it, sounds interesting

Tim Boudreau

unread,
Nov 23, 2013, 10:53:48 PM11/23/13
to google...@googlegroups.com
FWIW, Giulius - https://github.com/timboudreau/giulius - also deals with binding command line arguments to @Named variables (and providing default values if no value is on the command line) - when setting up your Settings, do 

        Settings settings = SettingsBuilder
                .forNamespace("my-server")
                .addDefaultLocations()
                .parseCommandLineArguments(args).build();

        Dependencies deps = Dependencies.builder().add(settings, Namespace.DEFAULT)
                 .add(yourModule).build(); // wraps the injector, or you can get it directly

        Foo foo = deps.getInstance(Foo.class);

and if your code looks for @Named("port") String foo, then if your app was started with, say,

java -jar myJar.jar --port 8080

you will get the value from the command line;  if not, it will look in /etc/my-server.properties,
~/my-server.properties and ./my-server.properties and lastly on the classpath (in META-INF/settings/my-server.properties)
for a value for it;  you can use e.g. @Defaults("port=8000") to provide a default value.

That way you get a unified way of setting up configurable settings, without needing to have special
command-line handling code beyond calling SettingsBuilder.parseCommandLineArguments(args).

-Tim

Reply all
Reply to author
Forward
0 new messages