Single setter for multiple optional @Named properties

1,627 views
Skip to first unread message

Jeremy Chone

unread,
Jul 1, 2010, 6:30:57 PM7/1/10
to google-guice
Let's say I would like to be able to optionally inject the three
following via Google Guice @Named inject.

- webServiceUrl
- webServiceUsername
- webServicePassword

But I do not want to require to have all the values in the property
map. I thought that @Inject(optional = true) and @Nullable would be my
friend, however, when I do the following, this inject method get
called only if all three properties are present in the property map.

@Inject(optional = true)
public void injectWebServiceProperties(
@Nullable
@Named("akui.webServiceURL") String webServiceUrl,
@Nullable
@Named("akui.webServiceUsername") String webServiceUsername,
@Nullable
@Named("akui.webServicePassword") String webServicePassword) {

if (webServiceUrl != null){
...
}

if (webServiceUsername != null){
...
}
if (webServicePassword != null){
...
}

}

So, to make each property truly optional I need to have one setter per
property.


Is this a wanted feature or a bug? Is there any way to avoid to have
one setter per property while keeping any of them optional?



Jeremy,

Anthony MULLER

unread,
Jul 2, 2010, 4:11:14 AM7/2/10
to google...@googlegroups.com
Hello,

I think you need one setter per property. (this is the traditional JavaBeans convention in fact)

Anthony

2010/7/2 Jeremy Chone <jeremy...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.


limpb...@gmail.com

unread,
Jul 2, 2010, 4:31:13 AM7/2/10
to google-guice
On Jul 1, 3:30 pm, Jeremy Chone <jeremy.ch...@gmail.com> wrote:
> Is this a wanted feature or a bug? Is there any way to avoid to have
> one setter per property while keeping any of them optional?

It's a feature. Although they're frequently confused, 'optional=true'
and @Nullable mean quite different things.

'@Inject(optional=true)' means that the injector should suppress any
error from not being able to fulfill the dependencies of an injection.
The injector will try its best to find bindings, even if that involves
creating just-in-time bindings. But if any of the parameters to a
method cannot be satisfied, the entire call is skipped.

'@Nullable' means that the injector will not report an error if a null
value is returned by the binding for an injection. The binding must
still exist. The only time @Nullable is useful is when you implement a
provider method (@Provides) or a provider class that may return null.

Maaartin-1

unread,
Jul 2, 2010, 5:37:12 AM7/2/10
to google...@googlegroups.com
IMHO, it's a sort-of bug or a missing feature. There's no nice solution
for the problem described. Quite often, a class knows suitable defaults
for missing ctor parameters and something like this should be supported.
Probably @Nullable is fine the way it works, but then there should be an
@Optional annotation on arguments allowing both a binding to null and a
missing binding.

You can achieve something like

@Inject
public void injectWebServiceProperties(
@Optional @Named("akui.webServiceURL") String webServiceUrl,
@Optional @Named("akui.webServiceUsername") String webServiceUsername,
@Optional @Named("akui.webServicePassword") String webServicePassword) {
...
}

only using field injection, which is obviously a bad thing. I've already
ran into this several times and I don't think it's so rare it should be
ignored.

Chris Tucker

unread,
Jul 2, 2010, 1:58:04 PM7/2/10
to google...@googlegroups.com
You can achieve what you want using a technique described on the FAQ page:
http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_can_I_inject_optional_parameters_into_a_constructor?

It's not the most elegant thing in the world (you'll need a *Holder class for each optional parameter, and you'll have to change the type of your ctor args), but it gets the job done and does so without requiring any nasty setter/field injection.

Chris

Maaartin-1

unread,
Jul 3, 2010, 1:17:15 PM7/3/10
to google...@googlegroups.com
On 10-07-02 19:58, Chris Tucker wrote:
> You can achieve what you want using a technique described on the FAQ page:
> http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_can_I_inject_optional_parameters_into_a_constructor?
>
> It's not the most elegant thing in the world (you'll need a *Holder
> class for each optional parameter, and you'll have to change the type of
> your ctor args), but it gets the job done and does so without requiring
> any nasty setter/field injection.

Not really, I need to do a setter/field injection in the Holder. This is
no problem, but one more class for each parameter is quite bad,
especially with my parameters being ints and strings, so I need an
annotation for each of them (I hate using @Named). This means 2 classes
per parameter, don't you feel it's too much?

Isn't this problem common enough to be solved? I'm quite sure, it'd
require only small changes in Guice. I feel that constructor injection
should be at least as good as setter/field injection in each aspect.

Willi Schönborn

unread,
Jul 2, 2010, 5:45:52 AM7/2/10
to google...@googlegroups.com
On 02/07/10 11:37, Maaartin-1 wrote:
> IMHO, it's a sort-of bug or a missing feature. There's no nice solution
> for the problem described. Quite often, a class knows suitable defaults
> for missing ctor parameters and something like this should be supported.
> Probably @Nullable is fine the way it works, but then there should be an
> @Optional annotation on arguments allowing both a binding to null and a
> missing binding.
>
> You can achieve something like
>
> @Inject
> public void injectWebServiceProperties(
> @Optional @Named("akui.webServiceURL") String webServiceUrl,
> @Optional @Named("akui.webServiceUsername") String webServiceUsername,
> @Optional @Named("akui.webServicePassword") String webServicePassword) {
> ...
> }
>
Honestly, using 3 setters would be sooo much cleaner and easier to read.

Willi Schönborn

unread,
Jul 2, 2010, 4:33:10 AM7/2/10
to google...@googlegroups.com
Or if null represents a valid value for your particular use case.

Maaartin-1

unread,
Jul 6, 2010, 11:32:05 AM7/6/10
to google...@googlegroups.com
On 10-07-02 11:45, Willi Sch�nborn wrote:
>> @Inject
>> public void injectWebServiceProperties(
>> @Optional @Named("akui.webServiceURL") String webServiceUrl,
>> @Optional @Named("akui.webServiceUsername") String webServiceUsername,
>> @Optional @Named("akui.webServicePassword") String webServicePassword) {
>> ...
>> }
>>
> Honestly, using 3 setters would be sooo much cleaner and easier to read.

Really? I see no reason for this, unless you generally prefer using
setters to using constructors. The constructor argument list gets very
long mostly because of the Named annotations, this is not nice, but no
real problem.

Jeremy Chone

unread,
Jul 7, 2010, 7:24:38 AM7/7/10
to google-guice
Thanks for the suggestion, but I am trying to minimize java code. But
interesting way of doing it.

On Jul 2, 10:58 am, Chris Tucker <c.j.tuc...@gmail.com> wrote:
> You can achieve what you want using a technique described on the FAQ page:http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#H...
> ?
> > google-guice...@googlegroups.com<google-guice%2Bunsubscribe@google groups.com>
> > .

Jeremy Chone

unread,
Jul 7, 2010, 7:27:44 AM7/7/10
to google-guice
Willi,

I might get back to this. But there is one thing I love about Google
Guice is that it reduces the number of line of code. I know this
should not be the ultimate goal, but I find the "java bean" setters/
getters is a little bit heavy in some cases, especially when 90% they
are the same single line setter/getter logic. C# has a better way of
hanling this IMO.

Jeremy,

On Jul 2, 2:45 am, Willi Schönborn <w.schoenb...@googlemail.com>
wrote:

Jeremy Chone

unread,
Jul 7, 2010, 7:29:22 AM7/7/10
to google-guice
I did not think about the field injection. What are the bad things
about field injection?

Jason Winnebeck

unread,
Jul 7, 2010, 8:09:03 AM7/7/10
to google...@googlegroups.com
Inability to unit test or use outside of Guice, unless you also provide a
constructor/setter (in which case the other injection methods can be used) or
break encapsulation by making the fields more visible.

Jason

Maaartin-1

unread,
Jul 7, 2010, 2:53:44 PM7/7/10
to google...@googlegroups.com
IMHO, there's hardly ever any need to use field injection, using setters
is better, but it breaks encapsulation as well. I prefer constructor
injection, although it sometimes leads to long parameter list, which is
awkward, especially when using inheritance.

Without constructor injection you obviously can't get your fields final
and your objects immutable.

Reply all
Reply to author
Forward
0 new messages