I was learning Java Spring and faced a problem while working with properties file. Property File value is not being read in xml file and throwing exception.
The XML file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="triangle1" class="com.springtest.shapes.Triangle">
<property name="pointA" ref="zeroPoint"/>
<property name="pointB" ref="point2" />
<property name="pointC" ref="point3" />
</bean>
<bean id="zeroPoint" class="com.springtest.shapes.Point">
<property name="x" value="#{pointA.pointX}" />
<property name="y" value="#{pointA.pointY}" />
</bean>
<bean id="point2" class="com.springtest.shapes.Point">
<property name="x" value="5" />
<property name="y" value="2" />
</bean>
<bean id="point3" class="com.springtest.shapes.Point">
<property name="x" value="-20" />
<property name="y" value="10" />
</bean>
<bean class="com.springtest.main.DisplayNameBeanPostProcessor"/>
<bean class="org.SpringFramework.beans.factory.config.PropertyPlaceHolderConfigurer">
<property name="locations">
<value>classpath:pointconfig.properties</value>
</property>
</bean>
</beans>
The Property file is as follows:
pointA.pointX=0
pointA.pointY=0
The following exception is being shown:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'pointA' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:100)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:87)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:52)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:111)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:270)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:163)
... 28 more
The Project Structure is also provided
Thanks in advance
I finally get the answer after continuous digging. Thanks Manish Shen from Youtube.
My Problem was,
I named the class name wrong. This class name was used in previous version of spring. The new class name is "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer".
The Value in the property of spring.xml should be written as "${pointA.pointX}" instead of "#{pointA.pointX}".
I am sharing the screenshot from where i got the answer.
Related
Not sure if it's possible since properties namespace is shared, but I was wondering how to make bean properties injection with values from a particular configuration file if there are few beans originating from same class and different only by bean Id.
For example, let's say there's a class Position
class Position{
int id;
String title;
}
And for each position there's a property file with values:
Employee.properties
id=1
title=Employee
Director.properties
id=2
name=Director
And XML configuration file looks like this:
<beans xmlns=.......>
<bean id="employeeProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:Employee.properties"/>
</bean>
<bean id="directorProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:Director.properties"/>
</bean>
<bean id="employee" class="com.example.title" lazy-init="true">
<property name="id" value="#{employeeProp.id}"/>
<property name="title" value="#{employeeProp.title}"/>
</bean>
<bean id="director" class="com.example.title" lazy-init="true">
<property name="id" value="#{directorProp.id}"/>
<property name="title" value="#{directorProp.title}"/>
</bean>
</beans>
Obviously that doesn't work because in #{employeeProp.id} I'm refering to id field of PropertyPlaceholderConfigurer object, not of the data it loaded from file.
Property or field 'id' cannot be found on object of type 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' - maybe not public?
I thought about to passing configuration as inner bean to constructor but that would unnecessary complicate class' logic.
How else (or If) it's possible to do properties injection based on values in different files without modifying class' logic?
Turns out you can use placeholderPrefix property for refering to exact config placeholder
So the resulting file would look like
<beans xmlns=.......>
<bean id="employeeProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:Employee.properties"/>
<property name="placeholderPrefix" value="employee-"/>
</bean>
<bean id="directorProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:Director.properties"/>
<property name="placeholderPrefix" value="director-"/>
</bean>
<bean id="employee" class="com.example.title" lazy-init="true">
<property name="id" value="employee-id}"/>
<property name="title" value="employee-title}"/>
</bean>
<bean id="director" class="com.example.title" lazy-init="true">
<property name="id" value="director-id}"/>
<property name="title" value="directorProp-title}"/>
</bean>
Note that I'm not using default value reference notation ${name} but name} because for some reason in case of using prefixes the former notation concatenates '${' to the value
I am new to Spring batch and trying to write multiple XML files for each record that I am going to read from database table. Suppose if I read 10 records, I need to create 10 XML files. One for each record.
The name for each XML file should be unique. For that, I am planning to use "column_name1" value but I am not sure how to achieve that. If anyone can help me in this then that would be a great help.
Updated:
Added the #{formsPMVRowMapper.id} to resource property which can point to DefaultOutboundIFMRowMapper(Custom implementation of RowMapper) where I created a class level variable to set the row id. but still it's not working since it tries to call getter of ID even before getting into mapRow method which I think correct behviour but I am not sure how to get hold of that ID which I can use as resource name for my file in multiXmlFileItemWriter.
Could someone please let me know what could be the possibly correct way to do this?
Below is my Spring batch configuration file.
<util:properties id="batchProperties">
<prop key="batch.output.file">${outbound.pmv.filename}</prop>
</util:properties>
<bean id="itemReader" parent="pagingItemReader">
<property name="queryProvider" ref="outboundQueryProvider" />
<property name="rowMapper" ref="pmvRowMapper" />
</bean>
<bean id="pmvRowMapper"
class="tx.oag.cs.txcses.arch.batch.readers.DefaultOutboundIFMRowMapper">
<property name="idName" value="outbound_locate_record_staging_id" />
</bean>
<bean id="outboundQueryProvider" class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="selectClause"
value="select column_name1" />
<property name="fromClause" value="from table_name" />
<property name="whereClause"
value="where column_name1='AAA' and column_name1='bbbb'" />
<property name="sortKey" value="column_name1" />
</bean>
<bean id="batchProcessor" parent="outboundStagingBatchProcessor">
<property name="entityClass"
value="Class_Name" />
</bean>
<bean id="itemWriter" parent="multiXmlFileItemWriter"/>
<bean id="multiXmlFileItemWriter"
class="org.springframework.batch.item.file.MultiResourceItemWriter">
<property name="resource" value="${outbound.ifm.outbound}/#{pmvRowMapper.id}">
</property>
<property name="delegate">
<bean class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="marshaller">
<bean class="tx.oag.cs.txcses.arch.batch.utils.XMLStringMarshaller" />
</property>
</bean>
</property>
<property name="itemCountLimitPerResource" value="1" />
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"
value="classpath:config/env/#{#env}/batch-outbound.properties" />
<property name="properties" ref="batchProperties" />
<property name="localOverride" value="true" />
</bean>
I understand that above "resource" property can only write files with same name but I am not sure how to use "resource" property well in co-ordination with "resourceSuffixCreator" property.
In our project we are using spring with Junit for Junit testing. We have used #ContextConfiguration annotation for loading multiple file. We have two classes AbstractContextJUnitTest and ContextJUnitTest and ContextJUnitTest extends AbstractContextJUnitTest.
During code flow I have noticed that same bean Id in multiple files with different bean types. When I am testing these Junits and getting the below error.
Error:
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean
named 'voterId' is expected to be of type [com.spring.test2.Student]
but was actually of type [com.spring.test2.Parent]
My requirement is Student bean should load with VoterId instead of Parent Bean.
Below are the java files and spring bean xml files:
test.xml:
<beans>
<context:annotation-config/>
<bean id="voterId" class="com.spring.test2.Parent">
<property name="Name" value="hai"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="system" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
test1.xml
<beans>
<context:annotation-config/>
<bean id="voterId" class="com.spring.test2.Student">
<property name="name" value="hello"/>
<property name="number" value="2080"/>
</bean>
</beans>
AbstractContextJUnitTest.java
#ContextConfiguration(locations="classpath:/com/spring/test2/test1.xml")
public class AbstractContextJUnitTest extends AbstractTransactionalJUnit4SpringContextTests{
}
ContextJUnitTest.java
#ContextConfiguration(locations={"classpath:/com/spring/test2/test.xml"})
public class ContextJUnitTest extends AbstractContextJUnitTest{
#Test
public void testStudent(){
Student stud=applicationContext.getBean("voterId",Student.class);
assertEquals(stud.getNumber(), 2080);
}
}
Did you tried #Primary?
<bean id="voterId" class="com.spring.test2.Student" primary="true">
<property name="name" value="hello"/>
<property name="number" value="2080"/>
</bean>
You have to use #Qualifier for com.spring.test2.Parent wherever you need.
Or you can get the bean with type as:
applicationContext.getBeansOfType(Student.class).get("voterId")
This is probably because you have extended classes in that order..and your test.xml doesn't have any bean with of Student. So it is simply following inheritance and found parent.
Below lines make it look for bean voterid in test.xml first and it found it there.
ContextConfiguration(locations={"classpath:/com/spring/test2/test.xml"}) public class ContextJUnitTest
I have a java.util.Properties object which has few key value pairs in it. I am trying to use this Property object in the spring configuration file i.e. define the key in the spring config and during runtime, it should get the value from the properties object.
For ex:
<bean id="test" class="com.sample.Test">
<constructor-arg value="${PROPERTY_KEY} />
</bean>
Now during the runtime, the constructor should get the value that is present in the Property object.
Is there a way to get this done ?
Note: I do not want to use config.properties here. Looking to use java.util.Properties
Thanks,
Rahul
<context:property-placeholder location="classpath:placeholder.properties"/>
or
<bean id="properties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:<file-name>.properties" />
</bean>
First you have to create bean to access your property file, like below
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath*:localhost-mysql.properties</value>
<value>classpath*:mail-server.properties</value>
</list>
</property>
</bean>
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
Next you can access Key-Value pair from your property files, like below
<bean id="mailServerSettings" class="com.ratormonitor.app.context.EmailSettings">
<property name="host" value="${mail.server.host}" />
<property name="port" value="${mail.server.port}" />
<property name="username" value="${mail.server.username}" />
<property name="password" value="${mail.server.password}" />
<property name="requestContextPath" value="${request.context.path}" />
</bean>
Hope this code will solve your problem.
You can use Spring Expression Language (SpEL) to get a java object value in spring configuration xml file.
An example :
<property name="misfireInstruction"
value="#{T(org.quartz.CronTrigger).MISFIRE_INSTRUCTION_FIRE_ONCE_NOW}"/>
So this is how I did:
As I said I had a java.util.Properties object. I then created a CustomProperty class which extended PropertySource>
public class CustomPropertySource extends PropertySource<Map<String, Object>>
Then in my main class I did the following:
AbstractApplicationContext context = new ClassPathXmlApplicationContext(new String[] {springConfigLocation, false);
context.getEnvironment().getPropertySources.addlast(new CustomPropertySource("custom", propertiesObject));
conext.refresh();
And then in the spring config file, I had to add this:
<context: property-placeholder ignore-unresolvable="true"/>
So in this way, I could fetch values for the keys defined in the spring config file, just like how we get the values from property files.
Thanks,
Rahul
I have 2 different applications deployed in application server (glassfish). One is a jar file and other is a war application. Both the applications refer to a single properties file (data.properties). To read the properties file, I have created a instance of Springs PropertyPlaceholderConfigurer in respective context files (business-beans.xml and applicationContext.xml). After deploying the applications, I am able to load the properties file in one application while the other web application throws "Could not resolve placeholder 'sw.throttle.enable'
Question -
How to solve the issue?
Is it incorrect load the same properties file at two locations?
Is there a way I load the properties file in one context and in the other bean definition file use the reference of the first one?
SnapShot of business.beans
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="placeholderPrefix" value="${sw." />
<property name="location" value="file:///etc/data.properties" />
<property name="ignoreResourceNotFound" value="true" />
</bean>
Property referenced as below in business.beans
<bean id="mService" class=" com.test.business.mService">
<property name="throttlingEnabled" value="${sw.throttle.enable}"/>
</bean>
Snapshot of applicationContext.xml
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="placeholderPrefix" value="${sw." />
<property name="location" value="file:///etc/data.properties" />
<property name="ignoreResourceNotFound" value="true" />
</bean>
Property referenced as below in applicationContext.xml
<bean id="downloadService" class="com.test.downloadService"
init-method="startUp" destroy-method="shutDown"
p:throttlingEnabled="${sw.throttle.enable}" />
The application containing business.beans deploys well, but the application containing applicationContext.xml throw run time error "could not resolve placeholder sw.throttle.enable"
Note -
Both the applications are deployed in a OsGi Context.
Spring version is 3.0.1
Edit -
The applicationContext.xml has another bean defined as below. Could this be the cause?
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
</bean>
The issue was resolved by setting "ignoreUnresolvablePlaceholders" to "true". Apparently business.beans had nothing to do with the issue
Below is the modified configuration which solved the issue
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="placeholderPrefix" value="${sw." />
<property name="location" value="file:///etc/data.properties" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceHolders" value="true"
</bean>
Thanks StackOverflow for the answer +1