Announcement Announcement Module
No announcement yet.
Property injection without setter method? Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Property injection without setter method?

    Hi there,

    I'm relatively new to Spring, but I'm a big fan of dependency injection and have used Google Guice for quite a while now. So forgive me if this might turn out to be newbie question...
    One of the great things about DI, in my mind, is that you can get rid of a lot of boiler plate code that essentially just copies data around, like the good old setter methods:
        public void setSomeProperty(SomeProperty property)
   = property;
    With Guice or JSR-330, this can be simplified to
        @Inject SomeProperty property;
    Our application uses the application-context.xml to wire everything, and one of the beans is set up like this:
     <bean id="fpcaWebService" class="com.everyonecounts.fpca.admin.impl.FPCAWebServiceImpl">
      <property name="envelopeManager" ref="fpcaEnvelopeManager"/>
    The only way I can make this work properly seems to be by adding a setter method setEnvelopeManager(EnvelopeManager) to the bean, which introduces exactly the kind of boiler plate code that I'm trying to avoid. First, I tried using the @Autowired on the property field, but then I realized that it's not really autowired, since the bean is configured with a specific property. We're also using JAX-RS and Apache CXF, so I tried an @Context annotation as well, also to no avail.
    As the JSR-330 API is not on our build path, I haven't tried @Inject yet, but before I go down this road any further I wanted to make sure that I'm not barking up the wrong tree here.
    Is it at all possible to configure beans with specific <property> elements, without providing setter methods for all the properties?



  • #2
    Hi Mirko,

    If you have enabled annotations on the application context (<context:annotation-config/>), your envelopeManager should autowire without any problem.


    • #3
      I should probably add that I receive a NotWritablePropertyException if there is no setter method defined.


      • #4
        Thanks for your response. I do have <context:annotation-config/> enabled in my application context file, and, as far as I can tell, auto-wiring by name or type for other beans seems to work as expected. The problem seems to be specific to beans that contain <property> elements.


        • #5
          If it helps, this is the stack trace I get without the setter method:
           org.springframework.beans.NotWritablePropertyException: Invalid property 'envelopeManager' of bean class [com.everyonecounts.fpca.admin.impl.FPCAWebServiceImpl]: Bean property 'envelopeManager' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
                  at org.springframework.beans.BeanWrapperImpl.setPropertyValue(
                  at org.springframework.beans.BeanWrapperImpl.setPropertyValue(
                  at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(
                  at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(
                  ... 46 more


          • #6

            If you are autowiring, you don't need specify the </propery> in XML, actually you can't specify if the setter is not present.

            You only need to enable the annotation config and make your property (i.e. envelopeManager) @Autowired/@Inject in the code


            • #7
              Unfortunately, the property cannot be autowired by type, because there are multiple beans of the same type that are configured differently. If I wanted it to be autowired by name, I'd have to specify additional @Qualifier and/or @Value annotations in the code, which would move part of the configuration from the application-context.xml into the source code. In the spirit of DI, I'd like to keep all the configuration aspects out of the source code and completely encapsulated in the application-context.xml. I don't understand why autowired properties don't require a setter method, but <property> elements do.


              • #8
                Then what you can do is make your bean autowire by name.

                <bean id="fpcaWebService" class="com.everyonecounts.fpca.admin.impl.FPCAWebServiceImpl" autowire="byName">
                Note that this will make all the properties inside FPCAWebServiceImpl autowire by name.


                • #9
                  I don't understand why autowired properties don't require a setter method, but <property> elements do.
                  For this I suggest a read of the java bean specification, which is what spring uses, a property is defined by a getter/setter (or one of them to make a read or write only property). So by definition a property requires a setter.

                  Regarding the @Inject as you already mentioned you can use the associated @Qualifier (both are in the javax.inject package so you are still depending on standards). Regarding the autowire by name that isn't going to work with @Autowired/@Inject as that is by design on type unless a @Qualifer is used.