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=../>
Related
I am working on an application where I have two classes both implementing a common interface. So in time of bean declaration, I am going to mark one of them primary in my app-context.xml file. I can achieve this by simply declaring the primary bean like this:
<bean id="oracleImpl" class="com.me.dao.OracleImpl" primary="true">
</bean>
Now I don't want to hard code which of the beans is going to be the primary bean, rather want to read the true/false value from a properties file. So I went like this:
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="oracleImpl" class="com.me.dao.OracleImpl" primary="${oracle.primary}">
</bean>
<bean id="pgsqlImpl" class="com.me.dao.PgsqlImpl" primary="${pgsql.primary}">
</bean>
The values of oracle.primary and pgsql.primary are defined in the file jdbc.properties along with other jdbc (non-boolean) properties.
But it doesn't work and says, "'${oracle.primary}' is not a valid value for 'boolean'"
I have a feeling it is something to do with the xsd validators. Browsing through this site and google gave me this much idea, but got no real solution. Can any body help?
This will not work.
As of 3.2.5.RELEASE only the following bean definition elemets support property placeholder:
parent name
bean class name
factory bean name
factory method name
scope
property values
indexed constructor arguments
generic constructor arguments
See the BeanDefinitionVisitor's visitBeanDefinition method for the details. This method is used by the PlaceholderConfigurerSupport.
I would recommend you to create a feature request in the spring issue management system.
PS: if you create an issue please add a comment to the issues url.
I have created a spring configuration file that works well.
My next step was to separate user configuration properties from system properties.
I have decided to create additional xml file with beans that will be configured by the user.
I had problem to create few such logical beans encapsulating properties that will be used by real class beans:
I have found over the net an option to reference proprieties in such way:
UserConf.xml
<bean id="numberGuess" class="x...">
<property name="randomNumber" value="5"/>
<!-- other properties -->
</bean>
SystemConf.xml
<import resource="UserConf.xml" />
<bean id="shapeGuess" class="y...">
<property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>
<!-- other properties -->
</bean>
But my problem is that i need x... class to be something logical that shouldn't be initialized at all, and i don't want it to disclose any info of the class hierarchy of the system since it should be only in use configuration xml file.
Solution1 is to create a Java object representing this proprieties:
public class MyProps(...)
and add a bean parent in the spring system configuration:
<bean id="MyProps" class="path to MyProps"/>
in the user side change the previous bean to be:
<bean id="numberGuess" parent="MyProps">
<property name="randomNumber" value="5"/>
<!-- other properties -->
</bean>
Solution2 is to use flat configuration file just like Database.props, and load it using factory.
Solution3 is to use Spring Property Placeholder configuration to load properties from XML properties file (e.g. example), but here i simply don't know how to get a more complex nested structure of properties (properties need to be separated by different logical names, e.g. minNumber will be defined both under xAlgo and y algo).
I don't like to create new Java class only to deal with this problem or to move my user configuration to a flat props file (i need the xml structure), is their any other solution??
I will answer my own question, since it looks as the best solution for me (and much more simplistic than was suggested)
I will use PropertiesFactoryBean to do the work for me:
e.g.
UserConf.xml
<bean id="numberGuess" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="randomNumber">3</prop>
<!-- other properties -->
</bean>
SystemConf.xml
<import resource="UserConf.xml" />
<bean id="shapeGuess" class="y...">
<property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>
<!-- other properties -->
</bean>
First if you don't know about the property place holder you should take a look at that. Also #Value("${some.property:defaultvalue}") is something you should look at.
Second the word configuration is ambiguous in Spring. Spring uses this word but they mean developer configuration not user configuration. Despite what people say or think Spring is not a configuration engine.
I'm not sure what your trying to do but you should be aware that your configuration will not be adjusted at runtime which is frequently needed for something like "user" configuration. So most people write their own configuration layer.
Another thing you should take a look at is not using the XML configuration and instead use Java Configuration which will give you way more flexibility.
In the Spring Framework, how do you determine what "properties" and other related values are available to be set in the context.xml file(s)? For example, I need to set the isolation level of a TransactionManager. Would that be:
<property name="isolation" value="SERIALIZABLE" />
<property name="isolation_level" value="Isolation.SERIALIZABLE" />
or some other values?
Each bean represents a class, which you can easily find by class="" attribute. Now you simply open JavaDoc or source code of that class and look for all setters (methods following setFooBar() naming convention). You strip set prefix and un-capitalize the first character, making it fooBar. These are your properties.
In your particular case you are probably talking about PlatformTransactionManager and various implementations it has.
Putting the properties into . properties file is a good way of handling.
First define a properties file in your project structure. It is better to put .properties file with the same directory as spring applicationContext.xml.
Your properties file may seem like this :
isolation = "SERIALIZABLE"
isolation_level = Isolation.SERIALIZABLE
You can access this properties file by defining a spring bean like :
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:YourProperties.properties"/>
</bean>
Finally you can access these properties inside Spring beans like :
<bean id="BeanName" class="YourClass">
<property name="PropertyName1" value="${isolation}"/>
<property name="PropertyName" value="${isolation_level}"/>
</bean>
There is another way to inject these values using annotations.
Our project has two application contexts:
application-context.xml
application-context-test.xml
Currently each file has duplicate bean definitions. So for example the following bean would be in each application context:
<bean id="foo "class="com.foo">
<property name="bar">
<ref local="bar"/>
</property>
</bean>
The plan is to create another file for bean definitions so we can reuse the beans, however, if we put the above xml segment into its own file, there will be no reference to bar
Is there an easy way to solve this?
Please note that barwill be different in each application context.
Thanks!
<ref local="bar"/> has a specific meaning - it means that bar must be defined in the same file. In your case, that's too strict, so loosen it a bit:
<bean id="foo "class="com.foo">
<property name="bar" ref="bar"/>
</bean>
And then use <import resource="..."> to import this file where needed.
With this, bar must still exist, but it can be in any file that's part of the context, or in any of the parent contexts.
Sure, use a common context file that you import into both xml files.
<import resource="/common"/>
See 4.2.2.1. Composing XML-based configuration metadata
I would like to get inner bean by it's name. Is it possible with Spring API?
Right now I'm using such Spring 2.5 API
ConfigurableApplicationContext.getBean(String paramString)
Example of XML:
<bean id="parent" parent="t_Parent">
<property name="items">
<bean id="child" parent="t_Child">
<property name="ABC" value="test"/>
</bean>
</property>
</bean>
I would like to get inner (t_Child) bean by id "child". E.g. ConfigurableApplicationContext.getBean("child"). Spring can't find such bean (because it's inner). At the same time .getBean("parent") works fine.
Any thoughts?
You can't.
From the docs:
A element inside the or elements is used to define a so-called inner bean. An inner bean definition does not need to have any id or name defined, and it is best not to even specify any id or name value because the id or name value simply will be ignored by the container.
If you need it like that, define it as a regular bean.
You can't, but you can create you inner bean outside (so it's no longer an inner bean...) and then reference it inside the property:
<bean id="child" parent="t_Child">
<property name="ABC" value="test"/>
</bean>
<bean id="parent" parent="t_Parent">
<property name="items" ref="child"/>
</bean>
Apart from the other (mostly valid) answers and solutions, I guess the spring way would be to use the BeanWrapper interface:
final BeanWrapper bw =
new BeanWrapperImpl(applicationContext.getBean("parent"));
Object innerBean = bw.getPropertyValue("child");
But I guess that implies that there must be a getter for the property (not only a setter).
Reference:
BeanWrapper (javadoc, 2.5 version)
Bean manipulation and the BeanWrapper (reference, 2.5 version)
If you move up to Spring 3.x, you should be able to do this with the Spring Expression Language. There are examples of directly referencing a bean property from another property (like in link text). The code to do this from Java would be somewhat similar, although I can't find an exact example of this scenario.
However, I would say that if you're trying to use "getBean()", you're doing something wrong. You could just as easily use the SpEL in your context to define a bean or a bean property that references that inner bean.