How to Achieve Conditional Resource Import in a Spring Xml Context

How to achieve conditional resource import in a Spring XML context?

This is now completely possible, using Spring 4.

In your main application content file

<bean class="com.example.MyConditionalConfiguration"/>

And the MyConditionalConfiguration looks like

@Configuration
@Conditional(MyConditionalConfiguration.Condition.class)
@ImportResource("/com/example/context-fragment.xml")
public class MyConditionalConfiguration {
static class Condition implements ConfigurationCondition {
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// only load context-fragment.xml if the system property is defined
return System.getProperty("com.example.context-fragment") != null;
}
}
}

And then finally, you put the bean definitions you want included in the /com/example/context-fragment.xml

See the JavaDoc for @Conditional

Importing resource conditionally in spring application context

Use Spring profiles.

<beans profile="not_test">
<import resource="classpath:context/caching-context.xml" />
</beans>

More information in Spring documentation and on the blog post.

Spring Import resource based on property in properties file - without using spring profile - Conditional Context Loading

You can use Spring 4's Conditionals to achieve that behaviour

For instance:

@Configuration
@Conditional(MyConditionalProd.class)
@ImportResource("classpath*:prod-config.xml")
public class MyConditionalProdConfig {}

MyConditionalProd would implement the conditional logic:

public class MyConditionalProd implements ConfigurationCondition{

@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String property = context.getEnvironment().getProperty("someProperty");
if("prod".equals(property)) {
return true;
}else{
return false;
}
}

}

Conditionally import xml resource in Spring integration

Consider to use Spring Profiles

With that you should do something like this:



Where that <import> will be included only if http.flow profile is active.

Spring 3.1 PropertySourcesPlaceholderConfigurer and conditional import

Footnote [2] of your link:

[2]: Because processing of <import/> elements necessarily occurs before BeanFactoryPostProcessors are invoked, meaning that even PropertyPlaceholderConfigurer could not help here. Because the Environment and its set of PropertySources are configured before container refresh, placeholders in elements can be resolved against the Environment without any lifecycle issues.

UPDATE:

According to the javadoc for PropertySourcesPlaceholderConfigurer, PropertySourcesPlaceholderConfigurer is a BeanFactoryPostProcessor, so what the footnote really says is that the import is resolved before the PropertySourcesPlaceholderConfigurer is installed, so it will not work either (in fact, at the time the <import/> is resolved, the configurer might not even exist yet!) Yes, when it is installed it will look at the Environment, but you cannot use it to resolve inside an <import/>, because at that time no postprocessors are operative. And that includes PropertySourcesPlaceholderConfigurer.

Basically Spring XML context setup goes more or less like this:

  1. Context is created.
  2. Environment is set.
  3. XML is read (all XML, resolving imports if necessary). Bean definitions are created.
  4. BeanFactoryPostProcessors are installed and invoked, processing bean definitions.
  5. BeanPostProcessors are installed.
  6. Beans are instantiated according to the bean definitions. BeanPostProcessors are applied.

This is a similar problem as that which causes that you cannot use the order property of many postprocessors to apply a BeanPostProccesor before a BeanFactoryPostProcessor (to do something like make a PropertyPlaceholderConfigurer resolve placeholders from a @PersistenceContext): the behaviour is hardcoded in the Spring application context, so you have to work around it by specializing some Spring classes.

Does resource import order matters in Spring XML?

Yes, order matters. If you declare a bean in one imported file and then declare a bean with the same name in a subsequently imported file, the first bean declaration is overridden.

UPDATE: To more directly address your question, it is fine to have beans in earlier imports refer to beans in later imports. Order does not matter in this way.



Related Topics



Leave a reply



Submit