Rado
Rado

Reputation: 436

Howto inject simple config parameters to beans using Guice?

Is there a simple way to inject simple primitive type parameters (string and int) to the beans?

What i need is to find the guice equivalent of something like this from spring.xml:

<bean id="aBean" ...>
  <property name="fieldName" value="aStringValue"/>
  <property name="anotherFieldName" value="123"/>
</bean> 

The values could be constructor injected, field injected or method injected, but i don't want to use separate named annotation or factory or provider for every value that i need to pass to the bean.

EDIT: my solution

Here is what i finally came to. I think it is closest to what i'm looking for, but any improvements would be welcome.

I found that in the module, i can declare a provider method and use it to set any properties i need:

MyModule extends AbstractModule{
...
     @Provides @Named("testBean") MyTestBean createTestBean(MembersInjector<TestBean> mi){
        TestBean test = new TestBean();
        mi.injectMembers(test);
        test.setFieldName("aStringValue");
        test.setAnotherFieldName(123);

        return test;
      }
...
}

The good point is that the Provides method replaces the bind() for the bean and this way the actual line count doesn't increase much.

I'm still not 100% sure about any side effects, but it looks promising.

Upvotes: 1

Views: 3297

Answers (2)

Ryan Nelson
Ryan Nelson

Reputation: 4676

There are a couple different ways you could do this, including your way. The only drawback to using a Provider method is that it's essentially a hand-rolled factory that you have to remember to maintain. (And in this specific case, you're also not getting the benefits of constructor injection).

Absent a Provider method, you have to use a binding annotation of some kind. If @Named won't work for you, then you'd need to create an annotation for each binding.

bindConstant().annotatedWith(FieldName.class).to("aStringValue");

public SomeClass {
    public void setFieldName(@FieldName String fieldname) {}
}

In some cases this might require a 1-to-1 annotation per primitive/String instance to be bound. But I try to make my annotations somewhat orthogonal to the actual instance being described, preferring instead to use the annotation to describe the relationship between the bound objects and the injection points.

It's not always possible, but a whole group of related primitives could then potentially be described by a single binding annotation, as long as each primitive type is only used once in the set. So, this could hypothetically work:

 bindConstant().annotatedWith(MyAnnotation.class).to("aStringValue");
 bindConstant().annotatedWith(MyAnnotation.class).to(123);

Parenthetically, I'm curious why you can't used @Named annotations on the property, but you can use them on the injected bean?

Upvotes: 0

Jan Galinski
Jan Galinski

Reputation: 11993

There is a build in mechanism to inject properties.

Properties File:

name=jan
city=hamburg

Module

@Override
protected void configure() {
    Names.bindProperties(binder(), properties);
}

then in your bean, just inject by Name

class Customer {
  @Inject
  @Named("name")
  String name;
  ....
}

Upvotes: 1

Related Questions