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"/>
By marking this method as static , it can be invoked without causing instantiation of its declaring @Configuration class, thus avoiding the above-mentioned lifecycle conflicts. Note however that static @Bean methods will not be enhanced for scoping and AOP semantics as mentioned above.
Yes, A spring bean may have static methods too.
PostConstruct, this method will be called after the constructor. It can not be static because static methods can not access non static variables, methods and etc.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With