Spaideri Spaideri - 3 months ago 22
Java Question

Initializing Spring bean from static method from another Class?

I was trying to create Hibernate Validator bean, and run into this problem creating a bean from static factory method in another Class. I found a Spring way to get my Validator bean initialized (solution at the bottom), but the problem itself remains unsolved. Validator is used as example case here.

This is how I create the Validator instance in Java

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();


This is how I tried to create the bean in applicationContext.xml

<bean id="validatorFactory"
class="javax.validation.ValidatorFactory"
factory-method="javax.validation.Validation.buildDefaultValidatorFactory" />

<bean id="validator"
class="javax.validation.Validator"
factory-bean="validatorFactory"
factory-method="getValidator" />


What I understand is that in "factory-method" you can only access static methods defined in the Class defined in the "class" parameter. Since the method buildDefaultValidatorFactory() is static I cant create a instance of Validation and give it as "factory-bean" for the validatorFactory like this:

<bean id="validation" class="javax.validation.Validation" />

<bean id="validatorFactory"
class="javax.validation.ValidatorFactory"
factory-bean="validation"
factory-method="buildDefaultValidatorFactory" />


This ends up to error message


"Check that a method with the specified name exists and that it is non-static"


Question is how would you create bean in this kind of a situation in Spring?

This is how I solved the Validator problem:

<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

Answer

The factory-method should only contain the method name, not including the class name.

If you want to use a static factory, give the class of the factory(!) to the bean declaration, if you want to use an instance factory, give the factory-bean to the bean declaration, but don't give both: The class of the created bean is not given in the bean declaration.

So a full example should look like this, using a static factory for validatorFactory and an instance factory for validator:

<bean id="validatorFactory" 
    class="javax.validation.Validation" 
    factory-method="buildDefaultValidatorFactory" />

<bean id="validator" 
    factory-bean="validatorFactory"
    factory-method="getValidator" />

See details on the documentation:

http://static.springsource.org/spring/docs/2.0.x/reference/beans.html#beans-factory-class-static-factory-method

To answer you question - How would you create bean in this kind of a situation in Spring? - Do it exactly as shown here, or if you can, use a utility class like the LocalValidatorFactoryBean, which simplifies the Spring configuration.