Good day experts, I want to figure out why my case is not working properly.
Situation:
There is a class called AbstractCheckoutStepValidator and here is it's xml configuration:
<bean id="abstractCheckoutStepValidator" class="...checkout.steps.validation.AbstractCheckoutStepValidator" abstract="true">
<property name="checkoutFlowFacade" ref="checkoutFlowFacade"/>
<property name="checkoutFacade" ref="checkoutFacade"/>
</bean>
and code:
public abstract class AbstractCheckoutStepValidator implements CheckoutStepValidator
{
private CheckoutFacade checkoutFacade;
private CheckoutFlowFacade checkoutFlowFacade;
@Override
public abstract ValidationResults validateOnEnter(final RedirectAttributes redirectAttributes);
@Override
public ValidationResults validateOnExit()
{
return ValidationResults.SUCCESS;
}
public CheckoutFacade getCheckoutFacade()
{
return checkoutFacade;
}
@Required
public void setCheckoutFacade(final CheckoutFacade checkoutFacade)
{
this.checkoutFacade = checkoutFacade;
}
public CheckoutFlowFacade getCheckoutFlowFacade()
{
return checkoutFlowFacade;
}
@Required
public void setCheckoutFlowFacade(final CheckoutFlowFacade checkoutFlowFacade)
{
this.checkoutFlowFacade = checkoutFlowFacade;
}
}
and here is DefaultMultiStepCheckoutStepValidator class that extends AbstractCheckoutStepValidator and overrides it's getter
public class DefaultMultiStepCheckoutStepValidator extends AbstractCheckoutStepValidator {
private static final Logger LOGGER = Logger.getLogger(DefaultMultiStepCheckoutStepValidator.class);
@Resource(name = "companyCheckoutFacade")
private CompanyCheckoutFacade companyCheckoutFacade;
// omitted code
@Override
public CompanyCheckoutFacade getCheckoutFacade() {
return companyCheckoutFacade;
}
}
xml configuration for this class:
<bean id="defaultMultiStepCheckoutValidator" class="...checkout.steps.validation.impl.DefaultMultiStepCheckoutStepValidator" parent="abstractCheckoutStepValidator" />
From technical perspective it should be fine, if getter returns parent class then I can use one of it's subclasses in my case it is CompanyCheckoutFacade extends CheckoutFacade. ( I have a similar examples of it, like here:
@Override
protected CompanyCartFacade getCartFacade() {
return (CompanyCartFacade) super.getCartFacade();
}
but here I'm sure that returned bean can be casted to this subclass and that's why i'm calling getter from parent class and this getter works fine either in parent class or in subclass)
Also in the code, I'm injecting dependency via annotation and this field is not related to checkoutFacade field in parent class...
If I'm starting the server with the code above then I got the following error:
Error creating bean with name 'defaultMultiStepCheckoutValidator' defined in ServletContext resource [/WEB-INF/config/multi-step-checkout-config.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '...order.impl.DefaultCheckoutFacade' to required type '...facades.order.CompanyCheckoutFacade' for property 'checkoutFacade'; nested exception is java.lang.IllegalStateException: Cannot convert value of type '...order.impl.DefaultCheckoutFacade' to required type '...facades.order.CompanyCheckoutFacade' for property 'checkoutFacade': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:342) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.lambda$resolveManagedMap$1(BeanDefinitionValueResolver.java:453) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[?:?]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:451) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:181) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1697) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1442) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.lambda$resolveManagedMap$1(BeanDefinitionValueResolver.java:453) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[?:?]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:451) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:181) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1697) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1442) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:453) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:527) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:497) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:650) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:239) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:318) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
... 27 more
Question is:
From the error above I don't really understand why spring tries to convert property value of type '...order.impl.DefaultCheckoutFacade' to required type '...facades.order.CompanyCheckoutFacade' for property 'checkoutFacade'. I'm not using checkoutFacade property anywhere in my getter.
DefaultCheckoutFacade is the default implementation of CheckoutFacade interface and I'm sure that checkoutFacade ref in xml configuration refers to the correct implementation, here:
<alias name="defaultCheckoutFacade" alias="checkoutFacade"/>
<bean id="defaultCheckoutFacade" class="...order.impl.DefaultCheckoutFacade">
// properties are omitted
</bean>
I my class I'm saying that getter should return different implementation and that is it. To get rid of this error I just need to rename getter and do not override the one from parent class but I don't understand why approach which overrides getter does not work?
Thank you for spending your time / answering question.