Skip to content

Commit 0ff3dfe

Browse files
committed
Polishing
1 parent 38af6f5 commit 0ff3dfe

File tree

19 files changed

+147
-104
lines changed

19 files changed

+147
-104
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The sample is based on the sample create for the book [Spring Integration in Act
1111

1212
## Objective
1313

14-
This sample uses **Spring Batch Integration** to more easily use *Spring Batch* and *Spring Integration* together. The application will poll a directory for a file that contains 27 payment records. *Spring Batch* will subsequently process those payments.
14+
This sample uses **Spring Batch Integration** to more easily use *Spring Batch* and *Spring Integration* together. The application will poll a directory for a file that contains 27 payment records. *Spring Batch* will subsequently process those payments. If an error occurs the Job is resubmitted.
1515

1616
## Running the Sample
1717

@@ -30,5 +30,8 @@ Or via one line:
3030
As a result the final console output should be:
3131

3232
DONE!!
33-
exitStatus: COMPLETED; imported # of payments: 27
34-
33+
exitStatus: COMPLETED; # of payments imported: 27
34+
Sent '2' notifications:
35+
#1 Subject: 'Execution has STARTED', Message: 'Execution has STARTED'.
36+
#2 Subject: 'Execution has COMPLETED', Message: 'Execution has COMPLETED'.
37+

src/main/java/org/springframework/batch/integration/samples/payments/Account.java

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/main/java/org/springframework/batch/integration/samples/payments/ExecutionsToMailTransformer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323

2424
/**
2525
* @author Marius Bogoevici
26+
* @author Gunnar Hillert
2627
*/
2728
public class ExecutionsToMailTransformer {
2829

2930
@Transformer
3031
public Message<String> transformExecutionsToMail(JobExecution jobExecution) {
31-
String result = "Execution has ended " + jobExecution.getStatus().toString();
32+
String result = "Execution has " + jobExecution.getStatus().toString();
3233
return MessageBuilder.withPayload(result)
3334
.setHeader(MailHeaders.TO, "[email protected]")
3435
.setHeader(MailHeaders.FROM, "[email protected]").build();

src/main/java/org/springframework/batch/integration/samples/payments/JobExecutionsRouter.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,36 @@
1515
*/
1616
package org.springframework.batch.integration.samples.payments;
1717

18+
import java.util.ArrayList;
19+
import java.util.List;
20+
1821
import org.springframework.batch.core.BatchStatus;
1922
import org.springframework.batch.core.JobExecution;
2023
import org.springframework.integration.annotation.Router;
2124

2225
/**
2326
* @author Marius Bogoevici
27+
* @author Gunnar Hillert
2428
*/
2529
public class JobExecutionsRouter {
30+
2631
@Router
27-
public String routeJobExecution(JobExecution jobExecution)
28-
{
32+
public List<String> routeJobExecution(JobExecution jobExecution) {
33+
34+
final List<String> routeToChannels = new ArrayList<String>();
35+
2936
if (jobExecution.getStatus().equals(BatchStatus.FAILED)) {
30-
return "jobRestarts";
37+
routeToChannels.add("jobRestarts");
3138
}
3239
else {
33-
return "notifiableExecutions";
40+
41+
if (jobExecution.getStatus().equals(BatchStatus.COMPLETED)) {
42+
routeToChannels.add("completeApplication");
43+
}
44+
45+
routeToChannels.add("notifiableExecutions");
3446
}
47+
48+
return routeToChannels;
3549
}
3650
}

src/main/java/org/springframework/batch/integration/samples/payments/JobRestart.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.batch.integration.samples.payments;
1717

18+
import org.apache.commons.logging.Log;
19+
import org.apache.commons.logging.LogFactory;
1820
import org.springframework.batch.core.Job;
1921
import org.springframework.batch.core.JobExecution;
2022
import org.springframework.batch.core.JobParametersInvalidException;
@@ -27,8 +29,12 @@
2729

2830
/**
2931
* @author Marius Bogoevici
32+
* @author Gunnar Hillert
3033
*/
3134
public class JobRestart {
35+
36+
private static final Log logger = LogFactory.getLog(JobRestart.class);
37+
3238
@Autowired
3339
JobLauncher jobLauncher;
3440

@@ -37,6 +43,7 @@ public class JobRestart {
3743

3844
@ServiceActivator
3945
public void restartIfPossible(JobExecution execution) throws JobInstanceAlreadyCompleteException, JobParametersInvalidException, JobRestartException, JobExecutionAlreadyRunningException {
40-
jobLauncher.run(job, execution.getJobParameters());
46+
logger.info("Restarting job...");
47+
jobLauncher.run(job, execution.getJobParameters());
4148
}
4249
}

src/main/java/org/springframework/batch/integration/samples/payments/Main.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,17 @@
1515
*/
1616
package org.springframework.batch.integration.samples.payments;
1717

18-
import java.util.Scanner;
18+
import java.util.List;
1919

20-
import org.apache.log4j.Logger;
21-
import org.junit.Assert;
2220
import org.springframework.batch.core.ExitStatus;
2321
import org.springframework.batch.core.JobExecution;
24-
import org.springframework.batch.core.repository.JobRepository;
2522
import org.springframework.batch.integration.samples.payments.util.SpringIntegrationUtils;
26-
import org.springframework.beans.factory.annotation.Autowired;
27-
import org.springframework.beans.factory.annotation.Qualifier;
2823
import org.springframework.context.support.AbstractApplicationContext;
2924
import org.springframework.context.support.ClassPathXmlApplicationContext;
3025
import org.springframework.integration.Message;
3126
import org.springframework.integration.channel.QueueChannel;
3227
import org.springframework.jdbc.core.JdbcTemplate;
33-
28+
import org.springframework.mail.SimpleMailMessage;
3429

3530
/**
3631
* Starts the Spring Context and will initialize the Spring Integration routes.
@@ -40,16 +35,15 @@
4035
*/
4136
public final class Main {
4237

43-
private static final Logger LOGGER = Logger.getLogger(Main.class);
44-
4538
private Main() { }
4639

4740
/**
4841
* Load the Spring Integration Application Context
4942
*
5043
* @param args - command line arguments
44+
* @throws InterruptedException
5145
*/
52-
public static void main(final String... args) {
46+
public static void main(final String... args) throws InterruptedException {
5347

5448
System.out.println("\n========================================================="
5549
+ "\n Welcome to the Spring Batch Integration "
@@ -67,28 +61,40 @@ public static void main(final String... args) {
6761
context.registerShutdownHook();
6862

6963
final JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
70-
final QueueChannel statusesChannel = context.getBean("statuses", QueueChannel.class);
71-
final JobRepository jobRepository = context.getBean(JobRepository.class);
7264

7365
SpringIntegrationUtils.displayDirectories(context);
7466

75-
76-
final Scanner scanner = new Scanner(System.in);
77-
7867
System.out.println("\n========================================================="
7968
+ "\n "
8069
+ "\n Waiting for Job execution to finish. "
8170
+ "\n "
8271
+ "\n=========================================================" );
8372

84-
JobExecution jobExecution = ((Message<JobExecution>) statusesChannel.receive(120000)).getPayload();
85-
ExitStatus exitStatus = jobExecution.getExitStatus();
86-
Assert.assertEquals(ExitStatus.COMPLETED, exitStatus);
87-
int count = jdbcTemplate.queryForInt("select count(*) from payments");
73+
final QueueChannel completeApplicationChannel =
74+
context.getBean("completeApplication", QueueChannel.class);
8875

89-
System.out.println(String.format("\nDONE!!\nexitStatus: %s; imported # of payments: %s",
76+
@SuppressWarnings("unchecked")
77+
final Message<JobExecution> jobExecutionMessage = (Message<JobExecution>) completeApplicationChannel.receive();
78+
final JobExecution jobExecution = jobExecutionMessage.getPayload();
79+
final ExitStatus exitStatus = jobExecution.getExitStatus();
80+
final int count = jdbcTemplate.queryForObject("select count(*) from payments", Integer.class);
81+
82+
System.out.println(String.format("\nDONE!!\nexitStatus: %s; # of payments imported: %s",
9083
exitStatus.getExitCode(), count));
9184

85+
final StubJavaMailSender mailSender = context.getBean(StubJavaMailSender.class);
86+
final List<SimpleMailMessage> emails = mailSender.getSentSimpleMailMessages();
87+
final int numberOfSentNotifications = emails.size();
88+
89+
System.out.println(String.format("Sent '%s' notifications:", numberOfSentNotifications));
90+
91+
int counter = 1;
92+
for (SimpleMailMessage mailMessage : emails) {
93+
System.out.println(String.format("#%s Subject: '%s', Message: '%s'.",
94+
counter, mailMessage.getText(), mailMessage.getText()));
95+
counter++;
96+
}
97+
9298
System.exit(0);
9399

94100
}

src/main/java/org/springframework/batch/integration/samples/payments/PaymentChunkListener.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,35 @@
1717

1818
import java.util.List;
1919

20+
import org.apache.commons.logging.Log;
21+
import org.apache.commons.logging.LogFactory;
2022
import org.springframework.batch.core.listener.ItemListenerSupport;
23+
import org.springframework.batch.integration.samples.payments.model.Notification;
24+
import org.springframework.batch.integration.samples.payments.model.Payment;
25+
import org.springframework.batch.item.file.FlatFileParseException;
2126
import org.springframework.beans.factory.annotation.Autowired;
2227
import org.springframework.beans.factory.annotation.Qualifier;
2328
import org.springframework.integration.MessageChannel;
2429
import org.springframework.integration.support.MessageBuilder;
2530

2631
/**
2732
* @author Marius Bogoevici
33+
* @author Gunnar Hillert
2834
*/
2935
public class PaymentChunkListener extends ItemListenerSupport<Payment, Payment> {
3036

37+
private static final Log logger = LogFactory.getLog(PaymentChunkListener.class);
38+
3139
@Autowired
3240
@Qualifier("chunkExecutions")
3341
MessageChannel chunkNotificationsChannel;
3442

3543
@Override
3644
public void onReadError(Exception ex) {
45+
if (ex instanceof FlatFileParseException) {
46+
FlatFileParseException ffpe = (FlatFileParseException) ex;
47+
logger.error(String.format("Error reading data on line '%s' - data: '%s'", ffpe.getLineNumber(), ffpe.getInput()));
48+
}
3749
chunkNotificationsChannel.send(MessageBuilder.withPayload(new Notification(ex.getMessage(),true)).build());
3850
}
3951

src/main/java/org/springframework/batch/integration/samples/payments/PaymentFieldSetMapper.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@
1515
*/
1616
package org.springframework.batch.integration.samples.payments;
1717

18+
import org.springframework.batch.integration.samples.payments.model.Payment;
1819
import org.springframework.batch.item.file.mapping.FieldSetMapper;
1920
import org.springframework.batch.item.file.transform.FieldSet;
2021
import org.springframework.validation.BindException;
2122

2223
/**
2324
* @author Marius Bogoevici
25+
* @author Gunnar Hillert
2426
*/
2527
public class PaymentFieldSetMapper implements FieldSetMapper<Payment> {
2628

2729
@Override
2830
public Payment mapFieldSet(FieldSet fieldSet) throws BindException {
29-
Payment payment = new Payment();
31+
32+
final Payment payment = new Payment();
3033

3134
payment.setSourceAccountNo(fieldSet.readString("source"));
3235
payment.setDestinationAccountNo(fieldSet.readString("destination"));

src/main/java/org/springframework/batch/integration/samples/payments/PaymentWriter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.sql.DataSource;
2121

2222
import org.apache.log4j.Logger;
23+
import org.springframework.batch.integration.samples.payments.model.Payment;
2324
import org.springframework.batch.item.ItemWriter;
2425
import org.springframework.jdbc.core.JdbcTemplate;
2526
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;

src/main/java/org/springframework/batch/integration/samples/payments/StubJavaMailSender.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public class StubJavaMailSender implements JavaMailSender {
3838

3939
private final List<SimpleMailMessage> sentSimpleMailMessages = new ArrayList<SimpleMailMessage>();
4040

41-
4241
public StubJavaMailSender(MimeMessage uniqueMessage) {
4342
this.uniqueMessage = uniqueMessage;
4443
}
@@ -72,7 +71,7 @@ public void send(MimeMessagePreparator mimeMessagePreparator) throws MailExcepti
7271
}
7372

7473
public void send(MimeMessagePreparator[] mimeMessagePreparators) throws MailException {
75-
throw new UnsupportedOperationException("MimeMessagePreparator not supported");
74+
throw new UnsupportedOperationException("MimeMessagePreparator not supported");
7675
}
7776

7877
public void send(SimpleMailMessage simpleMessage) throws MailException {

src/main/java/org/springframework/batch/integration/samples/payments/config/CommonConfig.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import javax.sql.DataSource;
1919

2020
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
21-
import org.springframework.batch.integration.samples.payments.PaymentWriter;
2221
import org.springframework.context.annotation.Bean;
2322
import org.springframework.context.annotation.Configuration;
2423
import org.springframework.jdbc.core.JdbcTemplate;
@@ -40,7 +39,7 @@ public JdbcTemplate jdbcTemplate() {
4039

4140
@Bean
4241
public DataSource dataSource() {
43-
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
42+
final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
4443
builder.setType(EmbeddedDatabaseType.HSQL)
4544
.addScript("classpath:/org/springframework/batch/core/schema-drop-hsqldb.sql")
4645
.addScript("classpath:/org/springframework/batch/core/schema-hsqldb.sql")

src/main/java/org/springframework/batch/integration/samples/payments/Notification.java renamed to src/main/java/org/springframework/batch/integration/samples/payments/model/Notification.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.batch.integration.samples.payments;
16+
package org.springframework.batch.integration.samples.payments.model;
1717

1818
/**
1919
* @author Marius Bogoevici
20+
* @author Gunnar Hillert
2021
*/
2122
public class Notification {
23+
2224
private String message;
2325

2426
private boolean failure;
@@ -43,4 +45,11 @@ public boolean isFailure() {
4345
public void setFailure(boolean failure) {
4446
this.failure = failure;
4547
}
48+
49+
@Override
50+
public String toString() {
51+
return "Notification [message=" + message + ", failure=" + failure
52+
+ "]";
53+
}
4654
}
55+

src/main/java/org/springframework/batch/integration/samples/payments/Payment.java renamed to src/main/java/org/springframework/batch/integration/samples/payments/model/Payment.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.batch.integration.samples.payments;
16+
package org.springframework.batch.integration.samples.payments.model;
1717

1818
import java.math.BigDecimal;
19+
import java.text.SimpleDateFormat;
1920
import java.util.Date;
2021

2122
/**
2223
* @author Marius Bogoevici
24+
* @author Gunnar Hillert
2325
*/
2426
public class Payment {
2527

@@ -43,6 +45,12 @@ public Date getDate() {
4345
return date;
4446
}
4547

48+
public String getDateFormatted() {
49+
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
50+
return simpleDateFormat.format(date);
51+
}
52+
53+
4654
public void setDate(Date date) {
4755
this.date = date;
4856
}
@@ -65,9 +73,8 @@ public void setSourceAccountNo(String sourceAccountNo) {
6573

6674
@Override
6775
public String toString() {
68-
return "Payment [sourceAccountNo=" + sourceAccountNo
69-
+ ", destinationAccountNo=" + destinationAccountNo
70-
+ ", amount=" + amount + ", date=" + date + "]";
76+
return "Payment [sourceAcct#=" + sourceAccountNo
77+
+ ", destAcct#=" + destinationAccountNo
78+
+ ", amount=" + amount + ", date=" + getDateFormatted() + "]";
7179
}
72-
7380
}

0 commit comments

Comments
 (0)