How to iterate over a property file in Spring xml - spring

I have a property file Details2.txt and it is filled with some values like :
list.value=34
list.value=35
list.value=38
list.value=45
list.value=23
Now i want to iterate this in my spring xml and i am unable to do so
XML code (parts only) :
<context:property-placeholder location="Details2.txt" />
<constructor-arg>
<list>
<value>${list.value}</value>
</list>
</constructor-arg>
this gives only the last value in property file

A property file will be translated to a Properties object, which in turn is a subclass of Hashtable, which contains a one-to-one mapping from key to value. This means that the Properties object will indeed only contain the last value (since the previous ones will have been overwritten).
One common way of handing this problem in property files is to add a suffix to the keys:
list.value.1=34
list.value.2=35
list.value.3=36
list.value.4=37
but that doesn't help you when using Spring, since each property key will need to be explicitly specified in the XML file (and I'm assuming you don't know the exact number of items).
Your best bet would be to specify the items as a comma-separated list:
list.values=34,35,36,37
And then use a configuration trick, such as described here or here.

Related

Mule ESB 3.4 Context property

How can one access the properties loaded by context:place-holder in a scripting component other than having to use ${property-name}? I want to get to the object that holds these key value pairs. Something like context.getProperty("property-name").
Spring property placeholders are resolved at configuration time and not stored anywhere, so they cant be loaded afterwards.
If you need to store it you can always inject them into a bean and retrieve that from the registry.
Basically all you need to do is to declare your bean:
<spring:bean class="your.Bean" name="yourBean" >
<spring:property name="yourBeanAttribute" value="${somePlaceHolder}" />
</spring:bean>
and then you can retrieve it, and the somePlaceHolder value from the registry from within a scripting component/transformer:
<scripting:transformer doc:name="Script">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[
def val = muleContext.getRegistry().lookupObject('yourBean').getYourBeanAttribute()
]]></scripting:text>
</scripting:script>
</scripting:transformer>
HTH

When to use <ref bean> and when to use <ref local> in Spring?

When to use <ref bean="service" /> and when to use <ref local="service" /> in Spring?
Specifying the target bean by using the bean attribute of the ref tag is the most general form, and will allow creating a reference to any bean in the same BeanFactory/ApplicationContext (whether or not in the same XML file), or parent BeanFactory/ApplicationContext. The value of the bean attribute may be the same as either the id attribute of the target bean, or one of the values in the name attribute of the target bean.
<ref bean="someBean"/>
Specifying the target bean by using the local attribute leverages the ability of the XML parser to validate XML id references within the same file. The value of the local attribute must be the same as the id attribute of the target bean. The XML parser will issue an error if no matching element is found in the same file. As such, using the local variant is the best choice (in order to know about errors are early as possible) if the target bean is in the same XML file.
<ref local="someBean"/>
This is from the Spring source reference here
The local attribute on the ref element is no longer supported in the 4.0 beans xsd since it does not provide value over a regular bean reference anymore. Simply change your existing ref local references to ref bean when upgrading to the 4.0 schema.
<ref local="someBeanId"> should be used when you have a duplicate id in your parent-child config files and you want to distinguish between the two in either config file.
<ref parent="someBeanId"> should be used in the child config file to reference the parent id.
<ref bean="someBeanId"> should be used when you do not have a duplicate id in your parent-child config files.
<ref local=".."> requires that the bean being referenced is in the same config file.
<ref bean="..."> requires only it to be in the same context, or in a parent context.
The difference is primarily one of documentation. If you see <ref local="...">, then you know you need only look in the same file to find it. Other than that, there's not much difference. I would generally use <ref bean="..."> in most cases.
In spring 4.1
the local attribute is not valid.
i used in the parent xml a name attribute for the
and in the child file a referenced the bean by the alias i gave already.

spEL in Bean Definition File : How to get a value in an inline list?

Given an inline list from a properties file:
nameList=john,smith,junior
From the bean definition file, I want to always extract the first item in my list. In this case, I would extract 'john'.
Using Spring Framework 3.0.4.RELEASE, my bean property looks as follows:
<property name="mySingleName" value="${nameList}" />
This obviously gives me the whole list.
I attempted to use the following to get the first item in the name list, but was met with an error:
<property name="mySingleName" value="#{${nameList}[0]}" />
The error was:
BeanExpressionException:Exception parsing failed: After parsing a valid expression, there is still more data in the expression:'comma(,)'
I have looked in the Book "Spring In Action", and have looked at the Spring spEL Documentation on Springs website. I have also googled for a quite a bit. Unfortunately, most of the code examples are done in code and not on the spring definition files. Any assistance in this would be greatly appreciated.
In your example you are reading a "nameList" property as a String ( not as a java.util.List ). You would need to convert it to a list first:
<bean id="listOfNames" class="org.springframework.util.StringUtils" factory-method="commaDelimitedListToSet">
<constructor-arg type="java.lang.String" value="${nameList}"/>
</bean>
and then you can apply SPeL to it:
<property name="mySingleName" value="#{listOfNames[0]}" />
similar problem / solution here: Spring: Reading collections form property files

Dynamically configuring java beans based on property file in Spring

Wondering if there is a way to dynamically instantiate beans based on set of values in your property file using PropertyPlaceholderConfigurer class.
I have a java bean say Student with two attributes: "name" and "subject"
I have a property file with:
student.1.name=student1name
student.1.subject=student1subject
student.2.name=student2name
student.2.name=student2subject
Now I have a Classroom object that can take a list of students.
I am wondering if there is a way we could do this using Spring. The challenge here is that the number of students could vary.
If there was only one student object then:
<bean id="student" class="com.abc.Student">
<property name="name" value="${student.1.name}" />
<property name="subject"
value="${student.1.subject}" />
</bean>
<bean id="classRoom" class="com.abc.ClassRoom">
<property name="student" ref="student" />
</bean>
would have worked. But in this case we have a list of n Students. And the value of n could vary depending on the number of entries in the properties file.
I'm with Kevin--IMO you're going about this the wrong way.
One possible workaround would be to create a bean that takes the property file as an argument, reads it in, and exposes a list of students (which would need to be indexed on something, like the n in the existing property file).
The classroom bean could then use that list of students.
But it sure looks like you're trying to duplicate the functionality of a DB, without a DB, in an awkward way.
I don't think there's a way to do that with PropertyPlaceholderConfigurer. Usually when I have a situation like that I choose a configuration format of either JSON or XML and use GSON/Jackson/JAXB to unmarshall the data into objects.

Difference between using bean id and name in Spring configuration file

Is there any difference between using an id attribute and name attribute on a <bean> element in a Spring configuration file?
From the Spring reference, 3.2.3.1 Naming Beans:
Every bean has one or more ids (also
called identifiers, or names; these
terms refer to the same thing). These
ids must be unique within the
container the bean is hosted in. A
bean will almost always have only one
id, but if a bean has more than one
id, the extra ones can essentially be
considered aliases.
When using XML-based configuration
metadata, you use the 'id' or 'name'
attributes to specify the bean
identifier(s). The 'id' attribute
allows you to specify exactly one id,
and as it is a real XML element ID
attribute, the XML parser is able to
do some extra validation when other
elements reference the id; as such, it
is the preferred way to specify a bean
id. However, the XML specification
does limit the characters which are
legal in XML IDs. This is usually not
a constraint, but if you have a need
to use one of these special XML
characters, or want to introduce other
aliases to the bean, you may also or
instead specify one or more bean ids,
separated by a comma (,), semicolon
(;), or whitespace in the 'name'
attribute.
So basically the id attribute conforms to the XML id attribute standards whereas name is a little more flexible. Generally speaking, I use name pretty much exclusively. It just seems more "Spring-y".
Since Spring 3.1 the id attribute is an xsd:string and permits the same range of characters as the name attribute.
The only difference between an id and a name is that a name can contain multiple aliases separated by a comma, semicolon or whitespace, whereas an id must be a single value.
From the Spring 3.2 documentation:
In XML-based configuration metadata, you use the id and/or name attributes to specify the bean identifier(s). The id attribute allows you to specify exactly one id. Conventionally these names are alphanumeric ('myBean', 'fooService', etc), but may special characters as well. If you want to introduce other aliases to the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note, in versions prior to Spring 3.1, the id attribute was typed as an xsd:ID, which constrained possible characters. As of 3.1, it is now xsd:string. Note that bean id uniqueness is still enforced by the container, though no longer by XML parsers.
Either one would work. It depends on your needs:
If your bean identifier contains special character(s) for example (/viewSummary.html), it wont be allowed as the bean id, because it's not a valid XML ID. In such cases you could skip defining the bean id and supply the bean name instead.
The name attribute also helps in defining aliases for your bean, since it allows specifying multiple identifiers for a given bean.
let me answer below question
Is there any difference between using an id attribute and using a name attribute on a <bean> tag,
There is no difference. you will experience same effect when id or name is used on a <bean> tag .
How?
Both id and name attributes are giving us a means to provide identifier value to a bean (For this moment, think id means id but not identifier). In both the cases, you will see same result if you call applicationContext.getBean("bean-identifier"); .
Take #Bean, the java equivalent of <bean> tag, you wont find an id attribute. you can give your identifier value to #Bean only through name attribute.
Let me explain it through an example :
Take this configuration file, let's call it as spring1.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<bean id="foo" class="com.intertech.Foo"></bean>
<bean id="bar" class="com.intertech.Bar"></bean>
</beans>
Spring returns Foo object for, Foo f = (Foo) context.getBean("foo");
. Replace id="foo" with name="foo" in the above spring1.xml, You will still see the same result.
Define your xml configuration like,
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<bean id="fooIdentifier" class="com.intertech.Foo"></bean>
<bean name="fooIdentifier" class="com.intertech.Foo"></bean>
</beans>
You will get BeanDefinitionParsingException. It will say, Bean name 'fooIdentifier' is already used in this element. By the way, This is the same exception you will see if you have below config
<bean name="fooIdentifier" class="com.intertech.Foo"></bean>
<bean name="fooIdentifier" class="com.intertech.Foo"></bean>
If you keep both id and name to the bean tag, the bean is said to have 2 identifiers. you can get the same bean with any identifier.
take config as
<?xml version="1.0" encoding="UTF-8"?><br>
<beans ...>
<bean id="fooById" name="fooByName" class="com.intertech.Foo"></bean>
<bean id="bar" class="com.intertech.Bar"></bean>
</beans>
the following code prints true
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(...);
Foo fooById = (Foo) context.getBean("fooById")// returns Foo object;
Foo fooByName = (Foo) context.getBean("fooByName")// returns Foo object;
System.out.println(fooById == fooByName) //true
Is there difference in defining Id & name in ApplicationContext xml ? No
As of 3.1(spring), id is also defined as an xsd:string type.
It means whatever characters allowed in defining name are also allowed in Id.
This was not possible prior to Spring 3.1.
Why to use name when it is same as Id ?
It is useful for some situations, such as allowing each component in an application to refer to a common dependency by using a bean name that is specific to that component itself.
For example, the configuration metadata for subsystem A may refer to a DataSource via the name subsystemA-dataSource. The configuration metadata for subsystem B may refer to a DataSource via the name subsystemB-dataSource. When composing the main application that uses both these subsystems the main application refers to the DataSource via the name myApp-dataSource. To have all three names refer to the same object you add to the MyApp configuration metadata the following
<bean id="myApp-dataSource" name="subsystemA-dataSource,subsystemB-dataSource" ..../>
Alternatively, You can have separate xml configuration files for each sub-system and then you can make use of
alias to define your own names.
<alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/>
<alias name="subsystemA-dataSource" alias="myApp-dataSource" />
Both id and name are bean identifiers in Spring IOC container/ApplicationContecxt. The id attribute lets you specify exactly one id but using name attribute you can give alias name to that bean.
You can check the spring doc here.

Resources