Conditional Bean Loading based on environment variable - java

I am using spring xml configuration and want to load either bean if system environment property is set
For example ::
if(system.property is set as "A")
<bean id="A" class="mypackage.A">
</bean>
else
<bean id="B" class="mypackage.B">
</bean>
Is it possible with SpEl , similar post i found is Condition Bean loading but not of if else condition
as in this post we are using lazy initialization of loading bean based on if variable is present in system environment but no if,else condition is specified for bean loading.Please share if anybody has any idea how to achieve this.

You can use spring bean profiles
<beans profile="A">
<bean id="A" class="mypackage.A"></bean>
</beans>
<beans profile="B">
<bean id="A" class="mypackage.B"></bean>
</beans>
To activate one of these profiles you can set value of system property
spring.profiles.active to A or B
You can also use conditional bean filtering support provided in spring 4
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-conditional

Related

What is the xml equivalent of this bean configuration where an object is being passed for which there is no bean configuration defined?

I need to add OAuth client to a Spring 3 project. I need to use xml based configuration. And I want to know the xml equivalent of the following bean configuration I found in another Spring project. Note that there is an input parameter in the bean definition where an object of type OAuth2ClientContext is being passed (OAuth2ClientContext is an Interface) and is named clientContext. But no bean definition is written anywhere for clientContext. What does this mean? And how would you write this in xml?
#Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext clientContext){
return new OAuth2RestTemplate(oauth2Resource(), clientContext);
}
The configuration should be like this
<bean id="client" class="package.OAuth2ClientContext" />
<bean id="resource" class="package.Oauth2Resource" />
<bean id="restTemplate" class="package.Oauth2Resource">
<property name="nameOfPropertyResource" ref="resource" />
<property name="nameOfPropertyClient" ref="client" />
</bean>
are you sure that the bean client is not declared? Maybe it’s declared in some jar? If yes you should find it’s name and use the name in the ref

Inject Resolved Properties Object to Another Bean

I'd like to inject a java.util.Properties object into another bean through XML config. I have tried the solution listed here without success, presumably because the bean is being injected before the property resolution occurs. Is there a way that I can force the java.util.Properties object to be resolved before being injected to my class?
Below is the trimmed/edited version of what I have. PropertiesConsumingClass does receive the merged, but unresolved properties of a, b, and c properties files.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="allProperties" />
</bean>
<bean id="allProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="propertiesArray">
<util:list>
<util:properties location="classpath:a.properties" />
<util:properties location="classpath:b.properties" />
<util:properties location="classpath:c.properties" />
</util:list>
</property>
</bean>
<bean class="PropertiesConsumingClass">
<constructor-arg index="0" ref="allProperties" />
</bean>
Your example doesn't work because what Spring calls a property isn't the same thing as what Java calls a property. Basically, a Spring property lives in a <property> tag, and this is what gets resolved by PropertyPlaceholderConfigurer. You can also use property placeholders inside #Value annotations. Either way you have a string with ${} placeholders that get resolved, possibly the string is converted to the correct type, and injected into your bean.
java.util.Properties are used to resolve placeholders in Spring properties, but they aren't considered for resolution themselves. Any properties in a., b., or c.properties will be substituted into Spring property placeholders, but PropertyPlaceholderConfigurer doesn't know or care if the values it gets from those files have ${} in them.
Now, Spring Boot does resolve placeholders inside its config files, but it has special sauce to accomplish that. It's also a very opinionated library that wants to control your app's lifecycle and does lots of magical things behind the scenes, so it's very hard to adopt or drop except at the very beginning of a project.

What exactly do the following SpEL expression?

I have some doubt about what exactly do these 3 Spring SpEL example:
1) FIRST EXAMPLE:
<bean id="rewardsDb" class="com.acme.RewardsTestDatabase">
<property name="keyGenerator" value="#{strategyBean.databaseKeyGenerator}" />
</bean>
It seems to me that this code snippet injet an inner property named databaseKeyGenerator (that is inside the strategyBean bean). So in this case SpEL is used to access to a specific bean property in the classica OO logic. Is it true?
2) SECOND EXAMPLE:
<bean id="strategyBean" class="com.acme.DefaultStrategies">
<property name="databaseKeyGenerator" ref="myKeyGenerator"/>
</bean>
It seems to me that SpEL is not used, or am I missing something?
3) THIRD EXAMPLE:
<bean id="taxCalculator" class="com.acme.TaxCalculator">
<property name="defaultLocale" value="#{ systemProperties['user.region'] }"/>
</bean> Equivalent
It is used to inject a property value taken from a property file
Is it correct or I a missing something or am I misinterpreting the SpEL logic?
The first and second examples come together. The second actually uses no SpEL at all. Its sole purpose is to help understand the first one. So you are not missing something regarding the first two.
As for the third one, systemProperties is a predefined variable and you use it to access system properties. Except from the standard VM system properties you can also access those that you pass with -D when starting the application.
You can access a property file the same way, after creating a bean to reference them, by using the bean id instead of systemProperties. For example
<util:properties id="appProps" location="classpath:application.properties" />
and then
<property name="propOne" value="#{appProps['some.property'] }"/>

Set prefix for imported Spring XML resources

I have a Spring application context file that imports several other resources. However some of the resources in the imported files have similar names for example include1.xml has something like
<bean id="MyBean" class="...">
...
</bean>
The same bean id is used in include2.xml. Is there a way to set a prefix to the included beans or is there a way so restrict the scope of the included resource. For example something like.
<import resource="include1.xml" prefix="foo"/>
<import resource="include2.xml" prefix="bar"/>
Now in the parent file I can refer to foo.MyBean and bar.MyBean. If no such system exists is there any way to restrict scope so there is no bean id collisions, what is the best practice here?
No, there is no way to namespace the beans based on a file(beans defined later with the same name will override the one's defined earlier) however, you have the freedom to give them your own "name" - so potentially you can name all beans in your foo file:
<bean name="foo.bean1" class=../>
<bean name="foo.bean2" class=../>
and in your bar file, thus namespacing them manually:
<bean name="bar.bean1" class=../>
<bean name="bar.bean2" class=../>

Inject an external property into Spring context

I have three apps in a Spring 2.5 managed project that share some code and differ in details.
Each application has a property (java.lang.String) which is used before the application context is built.
Building the app context takes some time and cannot happen first. As such, it's defined in each individual application. This property is duplicated in the context definition since it is also needed there. Can I get rid of that duplication?
Is it possible to inject that property into my application context?
Have a look at PropertyPlaceholderConfigurer.
The Spring documentation talks about it here.
<bean id="myPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:my-property-file.properties"/>
<property name="placeholderPrefix" value="$myPrefix{"/>
</bean>
<bean id="myClassWhichUsesTheProperties" class="com.class.Name">
<property name="propertyName" value="$myPrefix{my.property.from.the.file}"/>
</bean>
You then have reference to that String to anywhere you'd like in your application context, constructor-arg, property etc.
With spring 3.0 you have the #Value("${property}"). It uses the defined PropertyPlaceholderConfigurer beans.
In spring 2.5 you can again use the PropertyPlaceholderConfigurer and then define a bean of type java.lang.String which you can then autowire:
<bean id="yourProperty" class="java.lang.String">
<constructor-arg value="${property}" />
</bean>
#Autowired
#Qualifier("yourProperty")
private String property;
If you don't want to deal with external properties,you could define some common bean
<bean id="parent" class="my.class.Name"/>
then initialize it somehow, and put into common spring xml file, lets say common.xml. After that, you can make this context as a parent for each or your apps - in your child context xml file:
<import resource="common.xml"/>
and then you can inject properties of your parent into the beans you're interested in:
<bean ...
<property name="myProperty" value="#{parent.commonProperty}"/>
...
</bean>

Categories