Synesso
Synesso

Reputation: 38978

Spring bean creation order, mixing @Configuration with @ImportResource

I am exposing some config to the system deployers via XML and keeping the rest in Configuration beans.

Some of my beans depend on beans from the XML file. But it seems Spring is not able to resolve this dependency.

The main config class:

@Configuration
@Import({FeatureTogglesConfig.class, LanguagesConfig.class ... }

The FeatureTogglesConfig class:

@Configuration
@ImportResource(value = "classpath*:**/features-config.xml")
public class FeatureTogglesConfig {

}

This reads the XML file to create... :

<bean id="featureManager" class="toggles.FeatureManager">
    <constructor-arg>
        <set value-type="toggles.Feature">
            <value>FAKE_LANGUAGES</value>
        </set>
    </constructor-arg>
</bean>

FAKE_LANGUAGES is an enum value. It requires FeatureManager to be autowired:

public enum Feature {

    FAKE_LANGUAGES;

    @Autowired
    private FeatureManager manager;

    public boolean isActive() {
        return manager.isActive(this);
    }

The LanguagesConfig uses the enum in a way that requires the feature manager to have been set:

@Bean(name = "fake-latin-language-group")
public FakeLatinLanguageGroup fakeLatinLanguageGroup() {
    return if FAKE_LANGUAGES.isActive() ? new FakeLatinLanguageGroup() : ... ;
}

However, the loading of LanguagesConfig throws a NullPointerException because manager is null. Spring has not been able to identify the dependency and wire the manager up.

I tried to fix this with the annotation @DependsOn("featureManager"), but then it complains that there's no such bean.

So it seems that the @Configuration beans take precedence over the @ImportResource directive and I can't have dependencies between the two. Is that right?

Upvotes: 2

Views: 2584

Answers (1)

zagyi
zagyi

Reputation: 17518

Enum values are created by the classloader outside of the control of the Spring container, so the @Autowired annotation on the manager field is ignored. You can verify that by changing the field's type to something obviously wrong (e.g. simply to Object), and see the Spring context being initialized without any problem, which would prove that it doesn't care about it at all.

Upvotes: 1

Related Questions