How to write retryable-exception-classes using Spring Batch Annotation? - spring

We're migrating from Spring Batch XML based application to latest Spring Boot 2.2.6.RELEASE version application at this moment.
I've the below XML Snippet which I want to convert it into the Annotation based Job. I am really struggling to find these options, as I went through https://docs.spring.io/spring-batch/docs/current/reference/html/step.html#taskletStep.
<batch:job id="myJob">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="reader" writer="writer" commit-interval="100" retry-limit="3" skip-limit="3">
<batch:retryable-exception-classes>
<batch:exclude class="org.springframework.dao.PessimisticLockingFailureException"/>
</batch:retryable-exception-classes>
<batch:skippable-exception-classes>
<batch:include class="org.springframework.dao.DeadlockLoserDataAccessException"/>
</batch:skippable-exception-classes>
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
Another snippet:
<bean id="retryPolicy" class="org.springframework.retry.policy.ExceptionClassifierRetryPolicy">
<property name="policyMap">
<map>
<entry key="org.springframework.dao.ConcurrencyFailureException">
<bean class="org.springframework.batch.retry.policy.SimplreRetryPolicy">
<property name="maxAttempts" value="3" />
</bean>
</entry>
<entry key="org.springframework.dao.DeadlockLoserDataAccessException">
<bean class="org.springframework.batch.retry.policy.SimplreRetryPolicy">
<property name="maxAttempts" value="5" />
</bean>
</entry>
</map>
</property>
</bean>

There is a toggle at the top of each page that lets you choose which configuration style (XML or Java) you want to see in the code examples:
Now for the retryable exceptions section, here is the code with XML config:
And the equivalent in Java config:
If you want to provide a custom retry policy, you can use FaultTolerantStepBuilder#retryPolicy.

Related

Is reading data with a Reader declared as a Java Class better than reading it with a Reader configured in the xml job configuration?

I need to create a batch job that reads from the database millions of rows and I am thinking which is the best approach to do it the fastest that can be done; I think that using sql native to read will be the best option but I am also want to know more infos about the spring batch configuration and I don't seem to finding what I am searching for.
I know there are 2 ways of reading data in a Spring batch job using a Reader.
inside a bean eg:
<batch:step id="fetchData" >
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="dataReader" processor="dataProcessor"
writer="dataWriter" commit-interval="100"/>
</batch:tasklet>
<bean id="dataReader"
class="org.springframework.batch.item.database.JdbcPagingItemReader"
scope="step">
<property name="dataSource" ref="dataSourceNative"/>
<property name="pageSize" value="100"/>
<property name="rowMapper" ref="RowsMapper"/>
<property name="queryProvider">
<bean class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="dataSourceNative"/>
<property name="selectClause"
value="SELECT a,b "/>
<property name="fromClause"
value="from table"/>
<property name="whereClause"
value="WHERE a="blabla"/>
</bean>
</property>
</bean>
using a Java Class
<property name="targetObject" ref="myClassDao" />
<property name="targetMethod" value="list" />
<property name="arguments">
<list>
<!-- add arguments list -->
</list>
</property>
</bean>
<bean id="myClassDao" class="path.to.MyClassDAO"
Is it the same thing to do any of this approaches or the 2nd one gives you more liberty?
If the answer is no, which option is better/fastest?
I am thinking if I want to read from the database but using hibernate to do it. Can be implemented with any of these approaches?

Loading Custom activiti.cfg.xml

I am learning activiti.
Where I created one java application in that I am using hibernate + Spring + activiti where we have activiti.cfg.xml.
I want to load only database details like datasource and hibernate properties programatically, other thing e.g asyncExecutorActivate, etc I want to do using activiti.cfg.xml.
e.g
Following need to set using Programatically
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="<set_Using_Program>" />
<property name="url" value="<set_Using_Program>" />
<property name="username" value="<set_Using_Program>" />
<property name="password" value="<set_Using_Program>" />
</bean>
This Information set using activiti.cgf.xml
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
</beans>
How to do?
You can simply inject your values from properties file and build your own engine based on them. such as data source. follow this tutorial
You can also build extensions on them see userguide
for Spring Boot you can configure process engine like this code. activitiproperties is a custom class that I write to get mail server parameters.
#Autowired
private SpringProcessEngineConfiguration springprocessengineconfiguration;
springprocessengineconfiguration.setMailServerHost(activitiproperties.getMailServerHost());
springprocessengineconfiguration.setMailServerPort(activitiproperties.getMailServerPort());
springprocessengineconfiguration.setMailServerUsername(activitiproperties.getMailServerUserName());
springprocessengineconfiguration.setMailServerPassword(activitiproperties.getMailServerPassword());
springprocessengineconfiguration.setMailServerDefaultFrom(activitiproperties.getMailServerDefaultFrom());
springprocessengineconfiguration.setMailServerUseSSL(activitiproperties.isMailServerUseSsl());
springprocessengineconfiguration.setMailServerUseTLS(activitiproperties.isMailServerUseTls());

How do I automatically reload my properties in my Spring XML appilcation context?

I’m using Spring 3.2.11.RELEASE. I currently have the following set up in my application context file for the purposes of loading a cron trigger based off a schedule defined in a properties file (the property = cron.schedule) …
<bean id="localPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
</bean>
…
<bean id="updateResourcesJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myService" />
<property name="targetMethod" value="myMethod" />
<property name="concurrent" value="true" />
</bean>
<bean id="updateResourcesCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="myJob" />
<property name="cronExpression" value="${cron.schedule}" />
</bean>
My question is, I would like to create an XML configuration in my context file that allows me to edit my properties file and have everything automatically reloaded without having to restart my server or re-deploy my application. I have read several places about Apache Commons Configuration, but I can’t figure out how to take the above and rewrite an XML config that would utilize the configuration.
Thanks for any help, - Dave

How to set proxy in HttpComponentsMessageSender?

I am working behind a firewall,where i am trying to access a soap web service.
i went over through the internet,but couldn't find anything for setting proxy in .
I am calling the webservice using spring-integration.
Spring-integration.xml
<bean id="messageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="connectionTimeout" value="10000"/>
<property name="readTimeout" value="10000"/>
</bean>
<bean id="soapMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="soapVersion">
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12"/>
</property>
</bean>
<int:gateway id="requestGateway" service-interface="main.java.com.as.poller.RequestGateway"
default-request-channel="requestchannel" default-reply-timeout="20000">
<int:method name="pushNotification" />
</int:gateway>
<int-ws:outbound-gateway id="pointbalance"
uri="url"
marshaller="marshaller" unmarshaller="marshaller"
request-channel="pointbalancechannel" message-sender="messageSender"
message-factory="soapMessageFactory">
<int-ws:request-handler-advice-chain>
<int:retry-advice max-attempts="${retry_limit}">
</int:retry-advice>
<bean class="main.java.com.as.poller.RetryAdvice" />
</int-ws:request-handler-advice-chain>
</int-ws:outbound-gateway>
I could find only examples using CommonsHttpMessageSender.But this is deprecated.Can anyone please help me on setting the proxy for HttpComponentsMessageSender for my xml configuration...
I did it using org.springframework.ws.transport.http.CommonsHttpMessageSender from a superb article https://onebyteatatime.wordpress.com/2009/04/08/spring-web-service-call-using-proxy-per-connection/ . But still i dont see any thing regarding HttpComponentsMessageSender.

spring batch flatfileitemreader input resource must exist error

I am new to spring and my java is rusty so please excuse me if this is a simple question.
I have a two step job. The first step is to query a MongoDB and write a file. The second step is to read the file and process it.
I am using FlatFileItemReader for the second step. In the first step, I am writing the file without specifying any path.
When I run the job from within sts, the first step creates the file in the project directory in my sts workspace folder.
The second step throws the input resource must exist exception. I tried a variety of options such as file://, file:/ and so on without any success.
Confused as to why the read doesn't look for the file in the same place that the write wrote to.
In any case, any help in resolving the issue will be appreciated.
The first step does not use a FlatFileItemWriter and is just a tasklet that writes the file using java.
Here's the config:
<batch:step id="step2">
<batch:tasklet>
<batch:chunk reader="customerItemReader" processor="customerProcessor" writer="mongodbItemWriter"
commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="loadFromMongo" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetObject">
<bean class="testMongo.MongoLoader"/>
</property>
<property name="targetMethod" value="loadFromMongo" />
</bean>
<bean id="customerItemReader"
class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:Customers.txt"/>
<property name="lineMapper" ref="customerLineMapper"/>
<bean id="customerLineMapper"
class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer" ref="customerLineTokenizer"/>
<property name="fieldSetMapper" ref="customerFieldSetMapper"/>
<bean id="customerLineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
</bean>
<bean id="customerFieldSetMapper" class="testMongo.CustomerFieldSetMapper">
</bean>
<bean id="customerProcessor" class="testMongo.CustomerItemProcessor">
</bean>
<bean id="mongodbItemWriter" class="org.springframework.batch.item.data.MongoItemWriter">
<property name="template" ref="mongoTemplate" />
<property name="collection" value="creditReport" />
</bean>
<!-- commenting out copied stuff from mkyong SpringBatch Example for now
<bean id="xmlItemReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="record" />
<property name="resource" value="classpath:xml/report.xml" />
<property name="unmarshaller" ref="reportUnmarshaller" />
</bean>
<bean id="reportUnmarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="record" value="com.mkyong.model.Report" />
</util:map>
</property>
</bean>
-->

Resources