I need to generate a file called: NEW_NAME_YYYY-MM-DD where YYYY-MM-DD is the current Date. Everything works fine except for when my batch tries to get the propertie tmp.dir it finds nothing and calls the directory null instead. This is the Writer class I am working with :
public class MyFileWriter extends FlatFileItemWriter {
#Value("${tmp.dir}")
private String tempDir;
public MyFileWriter(){
super();
setResource();
}
public void setResource() {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD");
String stringDate = sdf.format(new Date());
String myPath = tempDir + "/NEW_NAME_" + stringDate + ".csv";
Resource outputFile = new FileSystemResource(myPath);
this.setResource(outputFile);
}
}
and this is the bean definition placed in applicationContext.xml along with the property-placeholder for the properties file:
<bean id="csvWriter" class="org.conters.writer.MyFileWriter" scope="step">
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value=";" />
<property name="fieldExtractor">
<bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<property name="names" value="ad,customer,total" />
</bean>
</property>
</bean>
</property>
<property name="encoding" value="${csv.encoding}" />
</bean>
Any idea on why the propertie isn't injected??? and as for the properties file called batch.properties in my case it is well declared in the applicationcontext.
Related
Introduction
In order to extract some data from a database, I am trying to setup a basic hibernate and spring batch project. The goal is to provide one query (HQL) and based on this query the spring batch application extracts all the data to a flat file.
One of the requirements of the application is that the user should not have to configure the mappings of the columns. As such I am trying to create a DynamicRecordProcessor that evaluates the input and passes the input (a table for example Address) to the writer in such a way that the flat file item writer can use a PassThroughFieldExtractor.
Below the reader-processor-writer xml configuration:
<!-- Standard Spring Hibernate Reader -->
<bean id="hibernateItemReader" class="org.springframework.batch.item.database.HibernateCursorItemReader">
<property name="sessionFactory" ref="sessionFactory" />
<property name="queryString" value="from Address" />
</bean>
<!-- Custom Processor -->
<bean id="dynamicRecordProcessor" class="nl.sander.mieras.processor.DynamicRecordProcessor"/>
<!-- Standard Spring Writer -->
<bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="file:target/extract/output.txt" />
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value="|"/>
<property name="fieldExtractor">
<bean class="org.springframework.batch.item.file.transform.PassThroughFieldExtractor"/>
</property>
</bean>
</property>
</bean>
EDIT:
And the job configuration:
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="cacheableMappingLocations" value="classpath*:META-INF/mappings/*.hbm.xml"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" lazy-init="true">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Problem
My processor looks as following:
public class DynamicRecordProcessor<Input,Output> implements ItemProcessor<Input,Output> {
private static final String DELIMITER = "|";
private boolean areNamesSetup = false;
private List<String> names = new ArrayList<String>();
private Input item;
#SuppressWarnings("unchecked")
#Override
public Output process(Input item) throws Exception {
this.item = item;
initMapping();
return (Output) extract();
}
private void initMapping() {
if (!areNamesSetup) {
mapColumns();
}
areNamesSetup = true;
}
private void mapColumns() {
Field[] allFields = item.getClass().getDeclaredFields();
for (Field field : allFields) {
if (!field.getType().equals(Set.class) && Modifier.isPrivate(field.getModifiers())) {
names.add(field.getName());
}
}
}
private Object extract() {
List<Object> values = new ArrayList<Object>();
BeanWrapper bw = new BeanWrapperImpl(item);
for (String propertyName : this.names) {
values.add(bw.getPropertyValue(propertyName));
}
return StringUtils.collectionToDelimitedString(values, DELIMITER);
}
}
The table Address has the following field:
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="city_id", nullable=false)
public City getCity() {
return this.city;
}
And the corresponding column in city:
#Column(name="city_id", unique=true, nullable=false)
public Short getCityId() {
return this.cityId;
}
When using values.add(bw.getPropertyValue(propertyName)); with propertyName being "city" the following exception occurs:
org.hibernate.SessionException: proxies cannot be fetched by a stateless session
at org.hibernate.internal.StatelessSessionImpl.immediateLoad(StatelessSessionImpl.java:292)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:156)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:260)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
at nl.sander.mieras.localhost.sakila.City_$$_jvstc2c_d.toString(City_$$_jvstc2c_d.java)
at java.lang.String.valueOf(String.java:2982)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at org.springframework.util.StringUtils.collectionToDelimitedString(StringUtils.java:1132)
at org.springframework.util.StringUtils.collectionToDelimitedString(StringUtils.java:1148)
at nl.sander.mieras.processor.DynamicRecordProcessor.extract(DynamicRecordProcessor.java:52)
at nl.sander.mieras.processor.DynamicRecordProcessor.process(DynamicRecordProcessor.java:27)
The value, however, is availabe as shown in the screenshot below.
Concrete question: How can I get the value 300?
I have tried getting the value using reflection API, but I couldn't reach the actual value I want to get...
Reproduce
I have setup a public repo. However, you still need a local database to be able to reproduce exactly the issue. https://github.com/Weirdfishees/hibernate-batch-example. Any suggestions how isolate this issue further are more then welcome.
Just flip your reader to be state-full instead of stateless with the useStatelessSession property:
<!-- Standard Spring Hibernate Reader -->
<bean id="hibernateItemReader" class="org.springframework.batch.item.database.HibernateCursorItemReader">
<property name="sessionFactory" ref="sessionFactory" />
<property name="queryString" value="from Address" />
<property name="useStatelessSession" value="false" />
</bean>
I am new to Spring batch and I am trying to use Spring Batch with restartable feature. I am using MapJobRepositoryFactoryBean as Job repository. Everything looks fine. But when I run the same job multiple times I could see the execution time increasing considerably. I guess some memory leak is happening.If no job is running, I am cleaning the repository as well. But no luck. How do I know whats happening exactly. After running the same job for 4-5 times, the execution time is going to 2-3 times of the first execution.
<jpa:repositories base-package=".reference.data.repository"/>
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url"
value="jdbc:sqlserver://${reference-data-manager.database.hostname}:
${reference-data-manager.database.port};
database=${reference-data-manager.database.name};
user=${reference-data-manager.database.username};
password=${reference-data-manager.database.password}" />
</bean>
<bean id="simpleJobConfiguration" class="reference.job.SimpleJobConfiguration">
</bean>
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="importJob" class="org.springframework.batch.core.job.SimpleJob" scope="prototype">
<property name="jobRepository" ref="jobRepository"></property>
</bean>
<batch:step id="importCodesStep">
<batch:tasklet allow-start-if-complete="true">
<batch:chunk reader="codeMappingReader" writer="codeMappingWriter"
processor="codeMappingProcessor" commit-interval="${reference-data-manager.batch.size}"
skip-policy="reasonRemarkAssnSkipPolicy" skip-limit="${reference-data-manager.skip.limit}">
<batch:skippable-exception-classes>
<batch:include class="org.springframework.batch.item.ParseException"/>
</batch:skippable-exception-classes>
</batch:chunk>
</batch:tasklet>
<batch:listeners>
<batch:listener ref="reasonRemarkAssnStepListener"/>
<batch:listener ref="reasonRemarkAssnSkipListener"/>
</batch:listeners>
</batch:step>
<bean id="reasonRemarkAssnStepListener" class="reference.listeners.ReasonRemarkAssnStepListener">
</bean>
<bean id="reasonRemarkAssnSkipListener" class="reference.listeners.ReasonRemarkAssnSkipListener">
</bean>
<bean id="reasonRemarkAssnSkipPolicy" class="reference.listeners.ReasonRemarkAssnSkipPolicy">
<!-- <property name="skipLimit" value="5"/> -->
</bean>
<bean id="codeMappingWriter" class="reference.writer.ReasonRemarkAssnWriter" scope="step">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="codeMappingProcessor" class="reference.processors.ReasonRemarkAssnProcessor" scope="step">
<property name="userId" value="#{jobParameters['USER_ID']}" />
<property name="clientMnemonic" value="#{jobParameters['CLIENT_MENOMONIC']}" />
</bean>
<bean id="codeMappingReader" class="reference.readers.ReasonRemarkAssnReader" scope="step">
<property name="org" value="#{jobParameters['ORG']}"/>
<property name="resource" value="" />
<property name="linesToSkip" value="1" />
<property name="lineMapper">
<bean class="reference.mapper.ReasonRemarkAassnLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="Reason Code,Remark Code,Category,Category Priority,Ignore Insight Processing,Active,Comment" />
</bean>
</property>
<property name="fieldSetMapper" ref="reasonRemarkAssnMapper"/>
</bean>
</property>
</bean>
<bean id="reasonRemarkAssnMapper" class="reference.mapper.ReasonRemarkAssnMapper">
<property name="codeGroups" value="${reference-data-manager.code.groups}"></property>
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
</bean>
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean class="CryptoPropertyPlaceholderConfigurer">
<property name="configUtil" ref="configUtil" />
<property name="location"
value="file:config/reference-data-manager.conf" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean name="configUtil" class="CoreConfigUtil">
<property name="crypto" ref="crypto" />
</bean>
<bean id="referenceDataManager" class="reference.service.impl.ReferenceDataManagerImpl">
<property name="step" ref="importCodesStep"></property>
</bean>
Here is my job invocation...
#RestfulServiceAddress("/reference")
public class ReferenceDataManagerImpl implements ReferenceDataManager {
#Autowired
private JobLauncher jobLauncher;
#Autowired
IDataAccessService dataAccessService;
#Autowired
private IConfigurationServiceFactory configurationServiceFactory;
#Autowired
private SimpleJob job;
#Autowired
private TaskletStep step;
#Autowired
private SimpleJobConfiguration jobConfiguration;
#Autowired
private MapJobRepositoryFactoryBean jobRepository;
#Override
public Response importData(MultipartBody input, String org,
String userId, MessageContext mc) throws ServiceFault {
Response.ResponseBuilder builder = null;
ReasonRemarkAssnResponse responseObj = null;
boolean isSuccess = false;
UserInfo userInfo= dataAccessService.userInfoFindByUserId(userId);
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
List<Attachment> attachments = input.getAllAttachments();
DataHandler dataHandler = attachments.get(0).getDataHandler();
byte[] bFile = null;
if(null != dataHandler){
try {
InputStream is = dataHandler.getInputStream();
bFile = new byte[is.available()];
is.read(bFile);
is.close();
} catch (IOException e) {
//TODO
}
}
SimpleJobConfiguration.customStorage.put(org, bFile);
jobParametersBuilder.addLong(ReferenceConstants.JOB_PARAMS_USERID, userInfo.getId());
jobParametersBuilder.addString(ReferenceConstants.JOB_PARAMS_ORG, org);
jobParametersBuilder.addString(ReferenceConstants.JOB_PARAMS_TIME, Calendar.getInstance().getTime().toString());
String response = "{error:Error occured while importing the file}";
job.setName(ReferenceConstants.JOB_PARAMS_JOB_NAME_PREFIX+org.toUpperCase());
job.addStep(step);
job.setRestartable(true);
JobExecution execution = null;
try {
execution = jobLauncher.run(job, jobParametersBuilder.toJobParameters());
isSuccess = true;
} catch (JobExecutionAlreadyRunningException e) {
//TODO
}catch (JobRestartException e) {
//TODO
}catch (JobInstanceAlreadyCompleteException e) {
//TODO
}catch (JobParametersInvalidException e) {
//TODO
}
response = prepareResponse(responseObj);
synchronized (SimpleJobConfiguration.customStorage){
if(null != SimpleJobConfiguration.customStorage.get(org)){
SimpleJobConfiguration.customStorage.remove(org);
}
if(SimpleJobConfiguration.customStorage.isEmpty()){
jobRepository.clear();
}
}
builder = Response.status(Response.Status.OK);
builder.type(MediaType.APPLICATION_JSON);
builder.entity(response);
return builder.build();
}
}
Don't use the MapJobRepositoryFactoryBean unless it's for testing. That's all it's intended for.
You shouldn't be building a new Job instance with every call to the controller. If you have stateful components within a step, declare them as step scoped so that you get a new instance per step execution.
The Map based JobRepository keeps everything in memory. That's the idea. So as you execute more and more jobs, the repository is going to grow...eating up your space in memory.
For launching a job in a controller, give something like this a try:
#RestController
public class JobLaunchingController {
#Autowired
private JobLauncher jobLauncher;
#Autowired
private Job job;
#RequestMapping(value = "/", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.ACCEPTED)
public void launch(#RequestParam("name") String name) throws Exception {
JobParameters jobParameters =
new JobParametersBuilder()
.addString("name", name)
.toJobParameters();
this.jobLauncher.run(job, jobParameters);
}
}
I'm getting four 'no setter found for property 'xxxx' in class com.rusapp.batch.trans.OLFMWriter'. A fifth bean in that class does not have an error, inputQueue. The rest have errors in the xml below at each of the property lines.
The beans appear as such:
<bean id="inputQueue" class="com.rusapp.batch.trans.OLFMWriter">
<property name="inputQueue" value="${${ENV}_MQ_FM_INPUT_QUEUE}" />
</bean>
<bean id="replyQueue" class="com.rusapp.batch.trans.OLFMWriter">
<property name="replyQueue" value="${${ENV}_MQ_FM_REPLY_QUEUE}" />
</bean>
<bean id="mqConnectionFactory" class="com.rusapp.batch.trans.OLFMWriter">
<property name="mqConnectionFactory" ref="mqConnection" />
</bean>
<bean id="JMSDestination"
class="com.rusapp.batch.trans.OLFMWriter">
<property name="JMSDestination" ref="jmsDestinationResolver" />
</bean>
<bean id="JMSReplyTo"
class="com.rusapp.batch.trans.OLFMWriter">
<property name="JMSReplyTo" ref="jmsDestinationResolverReceiver" />
</bean>
The setters in the class appear as follows:
public static void setMqConnectionFactory(MQConnectionFactory _mqConnectionFactory) {
OLFMWriter._mqConnectionFactory = _mqConnectionFactory;
}
public static void setReplyQueue(String _replyQueue) {
OLFMWriter._replyQueue = _replyQueue;
}
public static void setJMSDestination(Destination _JMSDestination) {
OLFMWriter._JMSDestination = _JMSDestination;
}
public static void setJMSReplyTo(Destination _JMSReplyTo) {
OLFMWriter._JMSReplyTo = _JMSReplyTo;
}
public void setInputQueue(String inputQueue){
_inputQueue = inputQueue;
}
This is not my code and I'm not too knowledgeable with Spring yet but I can't find anything wrong with the setter names. I thought it was a workspace error but they have persisted through several restarts of Eclipse.
Can anyone find any obvious faults with this code?
Your setters are static which means that they don't conform to the java beans specification.
I think you'll want to use a MethodInvokingFactorybean instead.
<bean abstract="true" id="abstractParent" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="com.rusapp.batch.trans.OLFMWriter"/>
</bean>
<bean id="inputQueue" parent="abstractParent">
<property name="staticMethod" value="setInputQueue" />
<property name="arguments">
<list><value>${${ENV}_MQ_FM_INPUT_QUEUE}</value></list>
</property>
</bean>
<bean id="replyQueue" parent="abstractParent">
<property name="staticMethod" value="setReplyQueue" />
<property name="arguments">
<list><value>${${ENV}_MQ_FM_REPLY_QUEUE}</value></list>
</property>
</bean>
etc...
I have been handling an application in which we are using LDAP to fetch user details. Sometimes it will take more time to fetch user details. I want to implement time out on methods that fetch details so that we can avoid hanging transactions in server in worst case.
Here we are using LdapUtil class in which we have configured LdapTemplate class to fetch the required details.
How can we implement timeout on LDAP methods?
(In this case ldapTemplate.search(...) methods)
public class LdapUtil {
#Autowired(required = true)
#Qualifier(value = "ldapTemplateApp")
LdapTemplate ldapTemplate;
public Set < ProductGroup > findProducts(String UserId) {
final Set < ProductGroup > products = newHashSet();
// Lookup the user
String usrFilter = String.format(USERID_FILTER, globalUserId);
ldapTemplate.search("ou=Members", usrFilter, // note this line
new NameClassPairCallbackHandler() {
public void handleNameClassPair(NameClassPair nameClassPair) {
SearchResult result = (SearchResult) nameClassPair;
String user = result.getNameInNamespace();
String GrpFilter = String.format(GROUP_FILTER, user);
List < String > zonePrefixes = ldapTemplate.search("Zones", GrpFilter, // note this line
new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
return substringBeforeLast((String) attributes.get("cn").get(), "-") + "-";
}
});
}
});
products.remove(null);
return newHashSet(products);
}
}
We have one LDAP.xml in which ldapTemplete is configured
<beans xmlns="------">
<!-- LDAP -->
<bean id="contextSourceApp" class="org.springframework.ldap.pool.factory.PoolingContextSource">
<property name="contextSource" ref="contextSourceTargetApp" />
<property name="dirContextValidator">
<bean id="dirContextValidator"
class="org.springframework.ldap.pool.validation.DefaultDirContextValidator"/>
</property>
<property name="testOnBorrow" value="true" />
</bean>
<bean id="contextSourceTargetApp" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="${ldap.url}" />
<property name="base" value="${ldap.base.}" />
<property name="userDn" value="${ldap.user}" />
<property name="password" value="${ldap.password}" />
<property name="pooled" value="false" />
</bean>
<bean id="ldapTemplateApp" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSourceApp" />
</bean>
I have few queries:
How can we implement the TIMEOUT for LDAP methods and how to configure it?(In which class of LDAP framework timeout settings will be there)
Is there any way to configure them in xml file i.e. LDAP.xml(in this case)?
I found a solution.
I have added the following property in my ldap.xml file. So far it worked for me.
<bean id="contextSourceTargetApp"
class="org.springframework.ldap.core.support.LdapContextSource">
<property name="baseEnvironmentProperties">
<map>
<entry key="com.sun.jndi.ldap.connect.timeout" value="5000" />
</map>
</property>
</bean>
Please post any other solution if you have any idea about LDAP timeout implementation.
For ActiveDirectoryLdapAuthenticationProvider the solution with ldap.xml file did not work for me. Instead I added a jndi.properties file to the classpath with the following content:
com.sun.jndi.ldap.connect.timeout=500
I have created applicationContext with two PropertyPlaceholderConfigurer beans and accessing only one based on my input using context object. But, while accessing for the properties from "Service2Record" instance I am getting "Service1Record" properties values. Below is my sample code.
ApplicationContext.xml
<beans >
<context:component-scan base-package="com.test.record" />
<!-- Service1 Properties files -->
<bean id="service1"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations" >
<value>classpath:service_1.properties</value>
</property>
<property name="properties" >
<value>service1.class=com.test.record.ServiceRecord</value>
</property>
</bean>
<bean id="service1record" class="${service1.class}" />
<!-- Service2 Properties files -->
<bean id="service2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<value>classpath:service_2.properties</value>
</property>
<property name="properties">
<value>service2.class=com.test.record.ServiceRecord</value>
</property>
</bean>
<bean id="service2record" class="${service2.class}" />
ServiceRecord Bean : -
#Configuration
public class ServiceRecord {
#Value("${request_queue_name}")
private String requestQueueName;
#Value("${reply_queue_name}")
private String replyQueueName;
public String getRequestQueueName() {
return requestQueueName;
}
public String getReplyQueueName() {
return replyQueueName;
}
}
Test Main Class -
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:applicationContext.xml");
ServiceRecord serviceRecord = null;
String inputService = "SERVICE2";
if(inputService.equals("SERVICE1")){
serviceRecord = (ServiceRecord)context.getBean("service1record");
} else {
serviceRecord = (ServiceRecord)context.getBean("service2record");
}
System.out.println(" RequestQueueName : " + serviceRecord.getRequestQueueName());
}
And
service_1.properties
request_queue_name=SERVICE1.REQUEST
reply_queue_name=SERVICE1.REPLY
service_2.properties
request_queue_name=SERVICE2.REQUEST
reply_queue_name=SERVICE2.REPLY
Here, every time output is "RequestQueueName : SERVICE2.REQUEST". Can you please tell how to get the respective values based on the properties file?
Modified -
I have single PPHC, within that setting multiple prop files for the location property and multiple propertieArray as below.
<property name="locations">
<list>
<value>classpath:common-service.properties</value>
<value>classpath:search-service.properties</value>
<value>classpath:update-service.properties</value>
</list>
</property>
<property name="propertiesArray" >
<list>
<value>common.class=com.xyz.rabbitmq.record.CommonUtil</value>
<value>search.class=com.xyz.rabbitmq.record.SearchRecord</value>
<value>update.class=com.xyz.rabbitmq.record.UpdateRecord</value>
</list>
</property>
<bean id="commonrecord" class="${common.class}"/>
<bean id="searchrecord" class="${search.class}"/>
<bean id="updaterecord" class="${update.class}"/>
Here, keys are different in each properties file and getting the bean instance based on the search or update request type.
serviceRecord = (ServiceRecord)context.getBean("searchrecord");
Will this approach is correct for loading different files?
I would suggest you to use different keys in the properties files:
service_1.properties
service1.request_queue_name=SERVICE1.REQUEST
service1.reply_queue_name=SERVICE1.REPLY
service_2.properties
service1.request_queue_name=SERVICE2.REQUEST
service1.reply_queue_name=SERVICE2.REPLY
And different ServiceRecord files, ServiceRecord1.java ServiceRecord2.java each reads properites from relevant properites file. i.e. when a new properties set/file is added you need to add a new ServiceRecord file.
If you don't want to have multiple ServiceRecords, you can instead have a Util method ..
public String getProperty(String serviceName, String propertyName) {
return propertySource.getProperty(serviceName+"."+propertyName);
}
The bean PropertyPlaceholderConfigurer is a BeanFactoryPostProcessor. Before the beans will be created, it is called and modify the whole context (the definitions that can change), in this case, only one bfpp can change something. Here you can read more about this.