Apply spring-javaformat style for consistency with other projects

Resolves #4118
This commit is contained in:
Mahmoud Ben Hassine
2022-05-25 17:47:13 +02:00
parent b3fe088879
commit c4ad90b9b1
1626 changed files with 44478 additions and 45612 deletions

View File

@@ -1,106 +1,103 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.common;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Simple minded partitioner for a range of values of a column in a database
* table. Works best if the values are uniformly distributed (e.g.
* auto-generated primary key values).
*
* @author Dave Syer
*
*/
public class ColumnRangePartitioner implements Partitioner {
private JdbcOperations jdbcTemplate;
private String table;
private String column;
/**
* The name of the SQL table the data are in.
*
* @param table the name of the table
*/
public void setTable(String table) {
this.table = table;
}
/**
* The name of the column to partition.
*
* @param column the column name.
*/
public void setColumn(String column) {
this.column = column;
}
/**
* The data source for connecting to the database.
*
* @param dataSource a {@link DataSource}
*/
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
/**
* Partition a database table assuming that the data in the column specified
* are uniformly distributed. The execution context values will have keys
* <code>minValue</code> and <code>maxValue</code> specifying the range of
* values to consider in each partition.
*
* @see Partitioner#partition(int)
*/
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
int min = jdbcTemplate.queryForObject("SELECT MIN(" + column + ") from " + table, Integer.class);
int max = jdbcTemplate.queryForObject("SELECT MAX(" + column + ") from " + table, Integer.class);
int targetSize = (max - min) / gridSize + 1;
Map<String, ExecutionContext> result = new HashMap<>();
int number = 0;
int start = min;
int end = start + targetSize - 1;
while (start <= max) {
ExecutionContext value = new ExecutionContext();
result.put("partition" + number, value);
if (end >= max) {
end = max;
}
value.putInt("minValue", start);
value.putInt("maxValue", end);
start += targetSize;
end += targetSize;
number++;
}
return result;
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.common;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.batch.core.partition.support.Partitioner;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Simple minded partitioner for a range of values of a column in a database table. Works
* best if the values are uniformly distributed (e.g. auto-generated primary key values).
*
* @author Dave Syer
*
*/
public class ColumnRangePartitioner implements Partitioner {
private JdbcOperations jdbcTemplate;
private String table;
private String column;
/**
* The name of the SQL table the data are in.
* @param table the name of the table
*/
public void setTable(String table) {
this.table = table;
}
/**
* The name of the column to partition.
* @param column the column name.
*/
public void setColumn(String column) {
this.column = column;
}
/**
* The data source for connecting to the database.
* @param dataSource a {@link DataSource}
*/
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
/**
* Partition a database table assuming that the data in the column specified are
* uniformly distributed. The execution context values will have keys
* <code>minValue</code> and <code>maxValue</code> specifying the range of values to
* consider in each partition.
*
* @see Partitioner#partition(int)
*/
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
int min = jdbcTemplate.queryForObject("SELECT MIN(" + column + ") from " + table, Integer.class);
int max = jdbcTemplate.queryForObject("SELECT MAX(" + column + ") from " + table, Integer.class);
int targetSize = (max - min) / gridSize + 1;
Map<String, ExecutionContext> result = new HashMap<>();
int number = 0;
int start = min;
int end = start + targetSize - 1;
while (start <= max) {
ExecutionContext value = new ExecutionContext();
result.put("partition" + number, value);
if (end >= max) {
end = max;
}
value.putInt("minValue", start);
value.putInt("maxValue", end);
start += targetSize;
end += targetSize;
number++;
}
return result;
}
}

View File

@@ -20,11 +20,11 @@ import org.springframework.batch.item.ItemReader;
import org.springframework.lang.Nullable;
/**
* ItemReader implementation that will continually return a new object. It's
* generally useful for testing interruption.
*
* ItemReader implementation that will continually return a new object. It's generally
* useful for testing interruption.
*
* @author Lucas Ward
*
*
*/
public class InfiniteLoopReader implements ItemReader<Object> {
@@ -33,4 +33,5 @@ public class InfiniteLoopReader implements ItemReader<Object> {
public Object read() throws Exception {
return new Object();
}
}

View File

@@ -25,18 +25,19 @@ import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.ItemWriter;
/**
* Simple module implementation that will always return true to indicate that
* processing should continue. This is useful for testing graceful shutdown of
* jobs.
*
* Simple module implementation that will always return true to indicate that processing
* should continue. This is useful for testing graceful shutdown of jobs.
*
* @author Lucas Ward
* @author Mahmoud Ben Hassine
*
*
*/
public class InfiniteLoopWriter implements StepExecutionListener, ItemWriter<Object> {
private static final Log LOG = LogFactory.getLog(InfiniteLoopWriter.class);
private StepExecution stepExecution;
private int count = 0;
/**
@@ -66,4 +67,5 @@ public class InfiniteLoopWriter implements StepExecutionListener, ItemWriter<Obj
LOG.info("Executing infinite loop, at count=" + count);
}
}
}

View File

@@ -20,17 +20,19 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Wraps calls for 'Processing' methods which output a single Object to write
* the string representation of the object to the log.
*
* Wraps calls for 'Processing' methods which output a single Object to write the string
* representation of the object to the log.
*
* @author Lucas Ward
*/
public class LogAdvice {
private static Log log = LogFactory.getLog(LogAdvice.class);
public void doStronglyTypedLogging(Object item) {
if (log.isInfoEnabled()) {
log.info("Processed: " + item);
}
}
private static Log log = LogFactory.getLog(LogAdvice.class);
public void doStronglyTypedLogging(Object item) {
if (log.isInfoEnabled()) {
log.info("Processed: " + item);
}
}
}

View File

@@ -22,7 +22,7 @@ import org.springframework.batch.item.ExecutionContext;
/**
* @author Dave Syer
*
*
*/
public class OutputFileListener {
@@ -31,7 +31,7 @@ public class OutputFileListener {
private String inputKeyName = "fileName";
private String path = "file:./target/output/";
public void setPath(String path) {
this.path = path;
}
@@ -52,8 +52,7 @@ public class OutputFileListener {
inputName = executionContext.getString(inputKeyName);
}
if (!executionContext.containsKey(outputKeyName)) {
executionContext.putString(outputKeyName, path + FilenameUtils.getBaseName(inputName)
+ ".csv");
executionContext.putString(outputKeyName, path + FilenameUtils.getBaseName(inputName) + ".csv");
}
}

View File

@@ -1,54 +1,53 @@
/*
* Copyright 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.common;
/**
* Item wrapper useful in "process indicator" usecase, where input is marked as
* processed by the processor/writer. This requires passing a technical
* identifier of the input data so that it can be modified in later stages.
*
* @param <T> item type
*
* @see StagingItemReader
* @see StagingItemProcessor
*
* @author Robert Kasanicky
*/
public class ProcessIndicatorItemWrapper<T> {
private long id;
private T item;
public ProcessIndicatorItemWrapper(long id, T item) {
this.id = id;
this.item = item;
}
/**
* @return id identifying the input data (typically row in database)
*/
public long getId() {
return id;
}
/**
* @return item (domain object for business processing)
*/
public T getItem() {
return item;
}
}
/*
* Copyright 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.common;
/**
* Item wrapper useful in "process indicator" usecase, where input is marked as processed
* by the processor/writer. This requires passing a technical identifier of the input data
* so that it can be modified in later stages.
*
* @param <T> item type
* @see StagingItemReader
* @see StagingItemProcessor
* @author Robert Kasanicky
*/
public class ProcessIndicatorItemWrapper<T> {
private long id;
private T item;
public ProcessIndicatorItemWrapper(long id, T item) {
this.id = id;
this.item = item;
}
/**
* @return id identifying the input data (typically row in database)
*/
public long getId() {
return id;
}
/**
* @return item (domain object for business processing)
*/
public T getItem() {
return item;
}
}

View File

@@ -27,8 +27,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.Assert;
/**
* Thread-safe database {@link ItemReader} implementing the process indicator
* pattern.
* Thread-safe database {@link ItemReader} implementing the process indicator pattern.
*/
public class StagingItemListener extends StepListenerSupport<Long, Long> implements InitializingBean {

View File

@@ -1,74 +1,72 @@
/*
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.common;
import javax.sql.DataSource;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Marks the input row as 'processed'. (This change will rollback if there is
* problem later)
*
* @param <T> item type
*
* @see StagingItemReader
* @see StagingItemWriter
* @see ProcessIndicatorItemWrapper
*
* @author Robert Kasanicky
*/
public class StagingItemProcessor<T> implements ItemProcessor<ProcessIndicatorItemWrapper<T>, T>, InitializingBean {
private JdbcOperations jdbcTemplate;
public void setJdbcTemplate(JdbcOperations jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(jdbcTemplate, "Either jdbcTemplate or dataSource must be set");
}
/**
* Use the technical identifier to mark the input row as processed and
* return unwrapped item.
*/
@Nullable
@Override
public T process(ProcessIndicatorItemWrapper<T> wrapper) throws Exception {
int count = jdbcTemplate.update("UPDATE BATCH_STAGING SET PROCESSED=? WHERE ID=? AND PROCESSED=?",
StagingItemWriter.DONE, wrapper.getId(), StagingItemWriter.NEW);
if (count != 1) {
throw new OptimisticLockingFailureException("The staging record with ID=" + wrapper.getId()
+ " was updated concurrently when trying to mark as complete (updated " + count + " records.");
}
return wrapper.getItem();
}
}
/*
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.common;
import javax.sql.DataSource;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Marks the input row as 'processed'. (This change will rollback if there is problem
* later)
*
* @param <T> item type
* @see StagingItemReader
* @see StagingItemWriter
* @see ProcessIndicatorItemWrapper
* @author Robert Kasanicky
*/
public class StagingItemProcessor<T> implements ItemProcessor<ProcessIndicatorItemWrapper<T>, T>, InitializingBean {
private JdbcOperations jdbcTemplate;
public void setJdbcTemplate(JdbcOperations jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(jdbcTemplate, "Either jdbcTemplate or dataSource must be set");
}
/**
* Use the technical identifier to mark the input row as processed and return
* unwrapped item.
*/
@Nullable
@Override
public T process(ProcessIndicatorItemWrapper<T> wrapper) throws Exception {
int count = jdbcTemplate.update("UPDATE BATCH_STAGING SET PROCESSED=? WHERE ID=? AND PROCESSED=?",
StagingItemWriter.DONE, wrapper.getId(), StagingItemWriter.NEW);
if (count != 1) {
throw new OptimisticLockingFailureException("The staging record with ID=" + wrapper.getId()
+ " was updated concurrently when trying to mark as complete (updated " + count + " records.");
}
return wrapper.getItem();
}
}

View File

@@ -41,13 +41,12 @@ import org.springframework.util.Assert;
import org.springframework.util.SerializationUtils;
/**
* Thread-safe database {@link ItemReader} implementing the process indicator
* pattern.
* Thread-safe database {@link ItemReader} implementing the process indicator pattern.
*
* To achieve restartability use together with {@link StagingItemProcessor}.
*/
public class StagingItemReader<T> implements ItemReader<ProcessIndicatorItemWrapper<T>>, StepExecutionListener,
InitializingBean, DisposableBean {
public class StagingItemReader<T>
implements ItemReader<ProcessIndicatorItemWrapper<T>>, StepExecutionListener, InitializingBean, DisposableBean {
private static Log logger = LogFactory.getLog(StagingItemReader.class);
@@ -119,12 +118,12 @@ InitializingBean, DisposableBean {
@SuppressWarnings("unchecked")
T result = (T) jdbcTemplate.queryForObject("SELECT VALUE FROM BATCH_STAGING WHERE ID=?",
new RowMapper<Object>() {
@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
byte[] blob = rs.getBytes(1);
return SerializationUtils.deserialize(blob);
}
}, id);
@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
byte[] blob = rs.getBytes(1);
return SerializationUtils.deserialize(blob);
}
}, id);
return new ProcessIndicatorItemWrapper<>(id, result);
}

View File

@@ -60,7 +60,6 @@ public class StagingItemWriter<T> extends JdbcDaoSupport implements StepExecutio
/**
* Setter for the key generator for the staging table.
*
* @param incrementer the {@link DataFieldMaxValueIncrementer} to set
*/
public void setIncrementer(DataFieldMaxValueIncrementer incrementer) {
@@ -78,29 +77,28 @@ public class StagingItemWriter<T> extends JdbcDaoSupport implements StepExecutio
getJdbcTemplate().batchUpdate("INSERT into BATCH_STAGING (ID, JOB_ID, VALUE, PROCESSED) values (?,?,?,?)",
new BatchPreparedStatementSetter() {
@Override
public int getBatchSize() {
return items.size();
}
@Override
public int getBatchSize() {
return items.size();
}
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
Assert.state(itemIterator.nextIndex() == i, "Item ordering must be preserved in batch sql update");
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
Assert.state(itemIterator.nextIndex() == i,
"Item ordering must be preserved in batch sql update");
ps.setLong(1, incrementer.nextLongValue());
ps.setLong(2, stepExecution.getJobExecution().getJobId());
ps.setBytes(3, SerializationUtils.serialize(itemIterator.next()));
ps.setString(4, NEW);
}
});
ps.setLong(1, incrementer.nextLongValue());
ps.setLong(2, stepExecution.getJobExecution().getJobId());
ps.setBytes(3, SerializationUtils.serialize(itemIterator.next()));
ps.setString(4, NEW);
}
});
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.core.domain.StepListener#afterStep(StepExecution
* )
* @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution )
*/
@Nullable
@Override
@@ -118,4 +116,5 @@ public class StagingItemWriter<T> extends JdbcDaoSupport implements StepExecutio
public void beforeStep(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}

View File

@@ -37,22 +37,22 @@ import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
@Configuration
@PropertySource("classpath:/batch-hsql.properties")
public class DataSourceConfiguration {
@Autowired
private Environment environment;
@Autowired
private ResourceLoader resourceLoader;
@PostConstruct
protected void initialize() {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(resourceLoader.getResource(environment.getProperty("batch.schema.script")));
populator.setContinueOnError(true);
DatabasePopulatorUtils.execute(populator , dataSource());
DatabasePopulatorUtils.execute(populator, dataSource());
}
@Bean(destroyMethod="close")
@Bean(destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(environment.getProperty("batch.jdbc.driver"));

View File

@@ -32,7 +32,7 @@ import org.springframework.context.annotation.Configuration;
/**
* @author Dave Syer
* @author Mahmoud Ben Hassine
*
*
*/
@Configuration
@EnableBatchProcessing
@@ -51,7 +51,7 @@ public class RetrySampleConfiguration {
@Bean
protected Step step() {
return steps.get("step").<Trade, Object> chunk(1).reader(reader()).writer(writer()).faultTolerant()
return steps.get("step").<Trade, Object>chunk(1).reader(reader()).writer(writer()).faultTolerant()
.retry(Exception.class).retryLimit(3).build();
}
@@ -66,4 +66,5 @@ public class RetrySampleConfiguration {
protected ItemWriter<Object> writer() {
return new RetrySampleItemWriter<>();
}
}

View File

@@ -20,4 +20,5 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.data.repository.CrudRepository;
public interface CustomerCreditCrudRepository extends CrudRepository<CustomerCredit, Long> {
}

View File

@@ -22,6 +22,8 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface CustomerCreditPagingAndSortingRepository extends PagingAndSortingRepository<CustomerCredit, Long>{
public interface CustomerCreditPagingAndSortingRepository extends PagingAndSortingRepository<CustomerCredit, Long> {
Page<CustomerCredit> findByCreditGreaterThan(BigDecimal credit, Pageable request);
}

View File

@@ -20,209 +20,251 @@ import java.io.Serializable;
@SuppressWarnings("serial")
public class Game implements Serializable {
private String id;
private int year;
private String team;
private int week;
private String opponent;
private int completes;
private int attempts;
private int passingYards;
private int passingTd;
private int interceptions;
private int rushes;
private int rushYards;
private int receptions;
private int receptionYards;
private int totalTd;
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @return the year
*/
public int getYear() {
return year;
}
/**
* @return the team
*/
public String getTeam() {
return team;
}
/**
* @return the week
*/
public int getWeek() {
return week;
}
/**
* @return the opponent
*/
public String getOpponent() {
return opponent;
}
/**
* @return the completes
*/
public int getCompletes() {
return completes;
}
/**
* @return the attempts
*/
public int getAttempts() {
return attempts;
}
/**
* @return the passingYards
*/
public int getPassingYards() {
return passingYards;
}
/**
* @return the passingTd
*/
public int getPassingTd() {
return passingTd;
}
/**
* @return the interceptions
*/
public int getInterceptions() {
return interceptions;
}
/**
* @return the rushes
*/
public int getRushes() {
return rushes;
}
/**
* @return the rushYards
*/
public int getRushYards() {
return rushYards;
}
/**
* @return the receptions
*/
public int getReceptions() {
return receptions;
}
/**
* @return the receptionYards
*/
public int getReceptionYards() {
return receptionYards;
}
/**
* @return the totalTd
*/
public int getTotalTd() {
return totalTd;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @param year the year to set
*/
public void setYear(int year) {
this.year = year;
}
/**
* @param team the team to set
*/
public void setTeam(String team) {
this.team = team;
}
/**
* @param week the week to set
*/
public void setWeek(int week) {
this.week = week;
}
/**
* @param opponent the opponent to set
*/
public void setOpponent(String opponent) {
this.opponent = opponent;
}
/**
* @param completes the completes to set
*/
public void setCompletes(int completes) {
this.completes = completes;
}
/**
* @param attempts the attempts to set
*/
public void setAttempts(int attempts) {
this.attempts = attempts;
}
/**
* @param passingYards the passingYards to set
*/
public void setPassingYards(int passingYards) {
this.passingYards = passingYards;
}
/**
* @param passingTd the passingTd to set
*/
public void setPassingTd(int passingTd) {
this.passingTd = passingTd;
}
/**
* @param interceptions the interceptions to set
*/
public void setInterceptions(int interceptions) {
this.interceptions = interceptions;
}
/**
* @param rushes the rushes to set
*/
public void setRushes(int rushes) {
this.rushes = rushes;
}
/**
* @param rushYards the rushYards to set
*/
public void setRushYards(int rushYards) {
this.rushYards = rushYards;
}
/**
* @param receptions the receptions to set
*/
public void setReceptions(int receptions) {
this.receptions = receptions;
}
/**
* @param receptionYards the receptionYards to set
*/
public void setReceptionYards(int receptionYards) {
this.receptionYards = receptionYards;
}
/**
* @param totalTd the totalTd to set
*/
public void setTotalTd(int totalTd) {
this.totalTd = totalTd;
}
@Override
public String toString() {
return "Game: ID=" + id + " " + team + " vs. " + opponent +
" - " + year;
return "Game: ID=" + id + " " + team + " vs. " + opponent + " - " + year;
}
@Override
@@ -232,6 +274,7 @@ public class Game implements Serializable {
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -255,5 +298,5 @@ public class Game implements Serializable {
return true;
}
}

View File

@@ -20,63 +20,72 @@ import java.io.Serializable;
@SuppressWarnings("serial")
public class Player implements Serializable {
private String id;
private String lastName;
private String firstName;
private String position;
private int birthYear;
private String id;
private String lastName;
private String firstName;
private String position;
private int birthYear;
private int debutYear;
@Override
public String toString() {
return "PLAYER:id=" + id + ",Last Name=" + lastName +
",First Name=" + firstName + ",Position=" + position +
",Birth Year=" + birthYear + ",DebutYear=" +
debutYear;
return "PLAYER:id=" + id + ",Last Name=" + lastName + ",First Name=" + firstName + ",Position=" + position
+ ",Birth Year=" + birthYear + ",DebutYear=" + debutYear;
}
public String getId() {
return id;
}
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public String getPosition() {
return position;
}
public int getBirthYear() {
return birthYear;
}
public int getDebutYear() {
return debutYear;
}
public void setId(String id) {
this.id = id;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setPosition(String position) {
this.position = position;
}
public void setBirthYear(int birthYear) {
this.birthYear = birthYear;
}
public void setDebutYear(int debutYear) {
this.debutYear = debutYear;
}
}

View File

@@ -16,11 +16,11 @@
package org.springframework.batch.sample.domain.football;
/**
* Interface for writing {@link Player} objects to arbitrary output.
*/
public interface PlayerDao {
void savePlayer(Player player);
}

View File

@@ -16,103 +16,137 @@
package org.springframework.batch.sample.domain.football;
/**
* Domain object representing the summary of a given Player's
* year.
*
* Domain object representing the summary of a given Player's year.
*
* @author Lucas Ward
*/
public class PlayerSummary {
private String id;
private int year;
private int completes;
private int attempts;
private int passingYards;
private int passingTd;
private int interceptions;
private int rushes;
private int rushYards;
private int receptions;
private int receptionYards;
private int totalTd;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getCompletes() {
return completes;
}
public void setCompletes(int completes) {
this.completes = completes;
}
public int getAttempts() {
return attempts;
}
public void setAttempts(int attempts) {
this.attempts = attempts;
}
public int getPassingYards() {
return passingYards;
}
public void setPassingYards(int passingYards) {
this.passingYards = passingYards;
}
public int getPassingTd() {
return passingTd;
}
public void setPassingTd(int passingTd) {
this.passingTd = passingTd;
}
public int getInterceptions() {
return interceptions;
}
public void setInterceptions(int interceptions) {
this.interceptions = interceptions;
}
public int getRushes() {
return rushes;
}
public void setRushes(int rushes) {
this.rushes = rushes;
}
public int getRushYards() {
return rushYards;
}
public void setRushYards(int rushYards) {
this.rushYards = rushYards;
}
public int getReceptions() {
return receptions;
}
public void setReceptions(int receptions) {
this.receptions = receptions;
}
public int getReceptionYards() {
return receptionYards;
}
public void setReceptionYards(int receptionYards) {
this.receptionYards = receptionYards;
}
public int getTotalTd() {
return totalTd;
}
public void setTotalTd(int totalTd) {
this.totalTd = totalTd;
}
@Override
public String toString() {
return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards +
";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions +
";" + receptionYards + ";" + totalTd;
return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards
+ ";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions + ";"
+ receptionYards + ";" + totalTd;
}
@Override
@@ -146,4 +180,5 @@ public class PlayerSummary {
return true;
}
}

View File

@@ -23,16 +23,15 @@ import org.springframework.batch.repeat.exception.ExceptionHandler;
public class FootballExceptionHandler implements ExceptionHandler {
private static final Log logger = LogFactory
.getLog(FootballExceptionHandler.class);
private static final Log logger = LogFactory.getLog(FootballExceptionHandler.class);
@Override
public void handleException(RepeatContext context, Throwable throwable)
throws Throwable {
public void handleException(RepeatContext context, Throwable throwable) throws Throwable {
if (!(throwable instanceof NumberFormatException)) {
throw throwable;
} else {
}
else {
logger.error("Number Format Exception!", throwable);
}

View File

@@ -24,11 +24,11 @@ public class GameFieldSetMapper implements FieldSetMapper<Game> {
@Override
public Game mapFieldSet(FieldSet fs) {
if(fs == null){
if (fs == null) {
return null;
}
Game game = new Game();
game.setId(fs.readString("id"));
game.setYear(fs.readInt("year"));
@@ -45,7 +45,7 @@ public class GameFieldSetMapper implements FieldSetMapper<Game> {
game.setReceptions(fs.readInt("receptions", 0));
game.setReceptionYards(fs.readInt("receptionYards"));
game.setTotalTd(fs.readInt("totalTd"));
return game;
}

View File

@@ -42,14 +42,14 @@ public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter<Game> {
for (Game game : games) {
SqlParameterSource values = new MapSqlParameterSource().addValue("player_id", game.getId()).addValue(
"year_no", game.getYear()).addValue("team", game.getTeam()).addValue("week", game.getWeek())
.addValue("opponent", game.getOpponent()).addValue("completes", game.getCompletes()).addValue(
"attempts", game.getAttempts()).addValue("passing_yards", game.getPassingYards()).addValue(
"passing_td", game.getPassingTd()).addValue("interceptions", game.getInterceptions())
.addValue("rushes", game.getRushes()).addValue("rush_yards", game.getRushYards()).addValue(
"receptions", game.getReceptions()).addValue("receptions_yards", game.getReceptionYards())
.addValue("total_td", game.getTotalTd());
SqlParameterSource values = new MapSqlParameterSource().addValue("player_id", game.getId())
.addValue("year_no", game.getYear()).addValue("team", game.getTeam())
.addValue("week", game.getWeek()).addValue("opponent", game.getOpponent())
.addValue("completes", game.getCompletes()).addValue("attempts", game.getAttempts())
.addValue("passing_yards", game.getPassingYards()).addValue("passing_td", game.getPassingTd())
.addValue("interceptions", game.getInterceptions()).addValue("rushes", game.getRushes())
.addValue("rush_yards", game.getRushYards()).addValue("receptions", game.getReceptions())
.addValue("receptions_yards", game.getReceptionYards()).addValue("total_td", game.getTotalTd());
this.insertGame.execute(values);
}

View File

@@ -28,20 +28,20 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
* @author Lucas Ward
*
*/
public class JdbcPlayerDao implements PlayerDao {
public class JdbcPlayerDao implements PlayerDao {
public static final String INSERT_PLAYER =
"INSERT into PLAYERS (player_id, last_name, first_name, pos, year_of_birth, year_drafted)" +
" values (:id, :lastName, :firstName, :position, :birthYear, :debutYear)";
public static final String INSERT_PLAYER = "INSERT into PLAYERS (player_id, last_name, first_name, pos, year_of_birth, year_drafted)"
+ " values (:id, :lastName, :firstName, :position, :birthYear, :debutYear)";
private NamedParameterJdbcOperations namedParameterJdbcTemplate;
private NamedParameterJdbcOperations namedParameterJdbcTemplate;
@Override
@Override
public void savePlayer(Player player) {
namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player));
namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player));
}
public void setDataSource(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
public void setDataSource(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
}

View File

@@ -33,26 +33,27 @@ public class JdbcPlayerSummaryDao implements ItemWriter<PlayerSummary> {
+ "values(:id, :year, :completes, :attempts, :passingYards, :passingTd, "
+ ":interceptions, :rushes, :rushYards, :receptions, :receptionYards, :totalTd)";
private NamedParameterJdbcOperations namedParameterJdbcTemplate;
private NamedParameterJdbcOperations namedParameterJdbcTemplate;
@Override
public void write(List<? extends PlayerSummary> summaries) {
for (PlayerSummary summary : summaries) {
MapSqlParameterSource args = new MapSqlParameterSource().addValue("id", summary.getId()).addValue("year",
summary.getYear()).addValue("completes", summary.getCompletes()).addValue("attempts",
summary.getAttempts()).addValue("passingYards", summary.getPassingYards()).addValue("passingTd",
summary.getPassingTd()).addValue("interceptions", summary.getInterceptions()).addValue("rushes",
summary.getRushes()).addValue("rushYards", summary.getRushYards()).addValue("receptions",
summary.getReceptions()).addValue("receptionYards", summary.getReceptionYards()).addValue(
"totalTd", summary.getTotalTd());
MapSqlParameterSource args = new MapSqlParameterSource().addValue("id", summary.getId())
.addValue("year", summary.getYear()).addValue("completes", summary.getCompletes())
.addValue("attempts", summary.getAttempts()).addValue("passingYards", summary.getPassingYards())
.addValue("passingTd", summary.getPassingTd()).addValue("interceptions", summary.getInterceptions())
.addValue("rushes", summary.getRushes()).addValue("rushYards", summary.getRushYards())
.addValue("receptions", summary.getReceptions())
.addValue("receptionYards", summary.getReceptionYards()).addValue("totalTd", summary.getTotalTd());
namedParameterJdbcTemplate.update(INSERT_SUMMARY, args);
namedParameterJdbcTemplate.update(INSERT_SUMMARY, args);
}
}
public void setDataSource(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
public void setDataSource(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
}

View File

@@ -24,11 +24,11 @@ public class PlayerFieldSetMapper implements FieldSetMapper<Player> {
@Override
public Player mapFieldSet(FieldSet fs) {
if(fs == null){
if (fs == null) {
return null;
}
Player player = new Player();
player.setId(fs.readString("ID"));
player.setLastName(fs.readString("lastName"));
@@ -36,9 +36,8 @@ public class PlayerFieldSetMapper implements FieldSetMapper<Player> {
player.setPosition(fs.readString("position"));
player.setDebutYear(fs.readInt("debutYear"));
player.setBirthYear(fs.readInt("birthYear"));
return player;
}
}

View File

@@ -22,22 +22,25 @@ import org.springframework.batch.sample.domain.football.PlayerSummary;
import org.springframework.jdbc.core.RowMapper;
/**
* RowMapper used to map a ResultSet to a {@link org.springframework.batch.sample.domain.football.PlayerSummary}
*
* RowMapper used to map a ResultSet to a
* {@link org.springframework.batch.sample.domain.football.PlayerSummary}
*
* @author Lucas Ward
* @author Mahmoud Ben Hassine
*
*/
public class PlayerSummaryMapper implements RowMapper<PlayerSummary> {
/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int)
*/
@Override
public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException {
PlayerSummary summary = new PlayerSummary();
summary.setId(rs.getString(1));
summary.setYear(rs.getInt(2));
summary.setCompletes(rs.getInt(3));
@@ -50,7 +53,7 @@ public class PlayerSummaryMapper implements RowMapper<PlayerSummary> {
summary.setReceptions(rs.getInt(10));
summary.setReceptionYards(rs.getInt(11));
summary.setTotalTd(rs.getInt(12));
return summary;
}

View File

@@ -22,22 +22,25 @@ import org.springframework.batch.sample.domain.football.PlayerSummary;
import org.springframework.jdbc.core.RowMapper;
/**
* RowMapper used to map a ResultSet to a {@link org.springframework.batch.sample.domain.football.PlayerSummary}
*
* RowMapper used to map a ResultSet to a
* {@link org.springframework.batch.sample.domain.football.PlayerSummary}
*
* @author Lucas Ward
* @author Mahmoud Ben Hassine
*
*/
public class PlayerSummaryRowMapper implements RowMapper<PlayerSummary> {
/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int)
*/
@Override
public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException {
PlayerSummary summary = new PlayerSummary();
summary.setId(rs.getString(1));
summary.setYear(rs.getInt(2));
summary.setCompletes(rs.getInt(3));
@@ -50,7 +53,7 @@ public class PlayerSummaryRowMapper implements RowMapper<PlayerSummary> {
summary.setReceptions(rs.getInt(10));
summary.setReceptionYards(rs.getInt(11));
summary.setTotalTd(rs.getInt(12));
return summary;
}

View File

@@ -18,44 +18,47 @@ package org.springframework.batch.sample.domain.mail;
/**
* @author Dan Garrette
* @author Dave Syer
*
* @since 2.1
*/
public class User {
private int id;
private String name;
private String email;
public User() {
}
private int id;
public User( int id, String name, String email ) {
this.id = id;
this.name = name;
this.email = email;
}
private String name;
public int getId() {
return id;
}
private String email;
public void setId( int id ) {
this.id = id;
}
public User() {
}
public String getName() {
return name;
}
public User(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public void setName( String name ) {
this.name = name;
}
public int getId() {
return id;
}
public String getEmail() {
return email;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public void setEmail( String email ) {
this.email = email;
}
}

View File

@@ -18,23 +18,21 @@ package org.springframework.batch.sample.domain.mail.internal;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.mail.MailErrorHandler;
import org.springframework.mail.MailMessage;
/**
* This handler prints out failed messages with their exceptions. It also
* maintains a list of all failed messages it receives for lookup later by an
* assertion.
*
* This handler prints out failed messages with their exceptions. It also maintains a list
* of all failed messages it receives for lookup later by an assertion.
*
* @author Dan Garrette
* @author Dave Syer
*
* @since 2.1
*/
public class TestMailErrorHandler implements MailErrorHandler {
private static final Log LOGGER = LogFactory.getLog(TestMailErrorHandler.class);
private List<MailMessage> failedMessages = new ArrayList<>();
@@ -52,4 +50,5 @@ public class TestMailErrorHandler implements MailErrorHandler {
public void clear() {
this.failedMessages.clear();
}
}

View File

@@ -31,7 +31,6 @@ import org.springframework.mail.SimpleMailMessage;
* @author Dan Garrette
* @author Dave Syer
* @author Mahmoud Ben Hassine
*
* @since 2.1
*/
public class TestMailSender implements MailSender {

View File

@@ -25,24 +25,23 @@ import org.springframework.mail.SimpleMailMessage;
/**
* @author Dan Garrette
* @author Dave Syer
*
* @since 2.1
*/
public class UserMailItemProcessor implements
ItemProcessor<User, SimpleMailMessage> {
public class UserMailItemProcessor implements ItemProcessor<User, SimpleMailMessage> {
/**
* @see org.springframework.batch.item.ItemProcessor#process(java.lang.Object)
*/
@Nullable
/**
* @see org.springframework.batch.item.ItemProcessor#process(java.lang.Object)
*/
@Nullable
@Override
public SimpleMailMessage process( User user ) throws Exception {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo( user.getEmail() );
message.setFrom( "communications@thecompany.com" );
message.setSubject( user.getName() + "'s Account Info" );
message.setSentDate( new Date() );
message.setText( "Hello " + user.getName() );
return message;
}
public SimpleMailMessage process(User user) throws Exception {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(user.getEmail());
message.setFrom("communications@thecompany.com");
message.setSubject(user.getName() + "'s Account Info");
message.setSentDate(new Date());
message.setText("Hello " + user.getName());
return message;
}
}

View File

@@ -16,15 +16,15 @@
package org.springframework.batch.sample.domain.multiline;
/**
* A wrapper type for an item that is used by {@link AggregateItemReader} to
* identify the start and end of an aggregate record.
*
* A wrapper type for an item that is used by {@link AggregateItemReader} to identify the
* start and end of an aggregate record.
*
* @see AggregateItemReader
*
* @author Dave Syer
*
*
*/
public class AggregateItem<T> {
@SuppressWarnings("rawtypes")
private static final AggregateItem FOOTER = new AggregateItem<Object>(false, true) {
@Override
@@ -81,7 +81,6 @@ public class AggregateItem<T> {
/**
* Accessor for the wrapped item.
*
* @return the wrapped item
* @throws IllegalStateException if called on a record for which either
* {@link #isHeader()} or {@link #isFooter()} answers true.

View File

@@ -22,12 +22,11 @@ import org.springframework.util.Assert;
import org.springframework.validation.BindException;
/**
* Delegating mapper to convert form a vanilla {@link FieldSetMapper} to one
* that returns {@link AggregateItem} instances for consumption by the
* {@link AggregateItemReader}.
*
* Delegating mapper to convert form a vanilla {@link FieldSetMapper} to one that returns
* {@link AggregateItem} instances for consumption by the {@link AggregateItemReader}.
*
* @author Dave Syer
*
*
*/
public class AggregateItemFieldSetMapper<T> implements FieldSetMapper<AggregateItem<T>>, InitializingBean {
@@ -46,10 +45,8 @@ public class AggregateItemFieldSetMapper<T> implements FieldSetMapper<AggregateI
}
/**
* Public setter for the end field value. If the {@link FieldSet} input has
* a first field with this value that signals the start of an aggregate
* record.
*
* Public setter for the end field value. If the {@link FieldSet} input has a first
* field with this value that signals the start of an aggregate record.
* @param end the end to set
*/
public void setEnd(String end) {
@@ -57,9 +54,8 @@ public class AggregateItemFieldSetMapper<T> implements FieldSetMapper<AggregateI
}
/**
* Public setter for the begin value. If the {@link FieldSet} input has a
* first field with this value that signals the end of an aggregate record.
*
* Public setter for the begin value. If the {@link FieldSet} input has a first field
* with this value that signals the end of an aggregate record.
* @param begin the begin to set
*/
public void setBegin(String begin) {
@@ -76,14 +72,11 @@ public class AggregateItemFieldSetMapper<T> implements FieldSetMapper<AggregateI
}
/**
* Build an {@link AggregateItem} based on matching the first column in the
* input {@link FieldSet} to check for begin and end delimiters. If the
* current record is neither a begin nor an end marker then it is mapped
* using the delegate.
* Build an {@link AggregateItem} based on matching the first column in the input
* {@link FieldSet} to check for begin and end delimiters. If the current record is
* neither a begin nor an end marker then it is mapped using the delegate.
* @param fieldSet a {@link FieldSet} to map
*
* @return an {@link AggregateItem} that wraps the return value from the
* delegate
* @return an {@link AggregateItem} that wraps the return value from the delegate
* @throws BindException if one of the delegates does
*/
@Override

View File

@@ -25,24 +25,24 @@ import org.springframework.batch.item.ItemReader;
import org.springframework.lang.Nullable;
/**
* An {@link ItemReader} that delivers a list as its item, storing up objects
* from the injected {@link ItemReader} until they are ready to be packed out as
* a collection. This class must be used as a wrapper for a custom
* {@link ItemReader} that can identify the record boundaries. The custom reader
* should mark the beginning and end of records by returning an
* {@link AggregateItem} which responds true to its query methods
* <code>is*()</code>.<br><br>
*
* This class is thread-safe (it can be used concurrently by multiple threads)
* as long as the {@link ItemReader} is also thread-safe.
*
* An {@link ItemReader} that delivers a list as its item, storing up objects from the
* injected {@link ItemReader} until they are ready to be packed out as a collection. This
* class must be used as a wrapper for a custom {@link ItemReader} that can identify the
* record boundaries. The custom reader should mark the beginning and end of records by
* returning an {@link AggregateItem} which responds true to its query methods
* <code>is*()</code>.<br>
* <br>
*
* This class is thread-safe (it can be used concurrently by multiple threads) as long as
* the {@link ItemReader} is also thread-safe.
*
* @see AggregateItem#isHeader()
* @see AggregateItem#isFooter()
*
* @author Dave Syer
*
*
*/
public class AggregateItemReader<T> implements ItemReader<List<T>> {
private static final Log LOG = LogFactory.getLog(AggregateItemReader.class);
private ItemReader<AggregateItem<T>> itemReader;
@@ -102,14 +102,15 @@ public class AggregateItemReader<T> implements ItemReader<List<T>> {
}
/**
* Private class for temporary state management while item is being
* collected.
*
* Private class for temporary state management while item is being collected.
*
* @author Dave Syer
*
*
*/
private class ResultHolder {
private List<T> records = new ArrayList<>();
private boolean exhausted = false;
public List<T> getRecords() {
@@ -127,5 +128,7 @@ public class AggregateItemReader<T> implements ItemReader<List<T>> {
public void setExhausted(boolean exhausted) {
this.exhausted = exhausted;
}
}
}

View File

@@ -17,6 +17,7 @@
package org.springframework.batch.sample.domain.order;
public class Address {
public static final String LINE_ID_BILLING_ADDR = "BAD";
public static final String LINE_ID_SHIPPING_ADDR = "SAD";
@@ -146,4 +147,5 @@ public class Address {
return true;
}
}

View File

@@ -16,8 +16,8 @@
package org.springframework.batch.sample.domain.order;
public class BillingInfo {
public static final String LINE_ID_BILLING_INFO = "BIN";
private String paymentId;
@@ -85,4 +85,5 @@ public class BillingInfo {
return true;
}
}

View File

@@ -16,8 +16,8 @@
package org.springframework.batch.sample.domain.order;
public class Customer {
public static final String LINE_ID_BUSINESS_CUST = "BCU";
public static final String LINE_ID_NON_BUSINESS_CUST = "NCU";

View File

@@ -19,80 +19,88 @@ package org.springframework.batch.sample.domain.order;
import java.math.BigDecimal;
public class LineItem {
public static final String LINE_ID_ITEM = "LIT";
private long itemId;
private BigDecimal price;
private BigDecimal discountPerc;
private BigDecimal discountAmount;
private BigDecimal shippingPrice;
private BigDecimal handlingPrice;
private int quantity;
private BigDecimal totalPrice;
public static final String LINE_ID_ITEM = "LIT";
public BigDecimal getDiscountAmount() {
return discountAmount;
}
private long itemId;
public void setDiscountAmount(BigDecimal discountAmount) {
this.discountAmount = discountAmount;
}
private BigDecimal price;
public BigDecimal getDiscountPerc() {
return discountPerc;
}
private BigDecimal discountPerc;
public void setDiscountPerc(BigDecimal discountPerc) {
this.discountPerc = discountPerc;
}
private BigDecimal discountAmount;
public BigDecimal getHandlingPrice() {
return handlingPrice;
}
private BigDecimal shippingPrice;
public void setHandlingPrice(BigDecimal handlingPrice) {
this.handlingPrice = handlingPrice;
}
private BigDecimal handlingPrice;
public long getItemId() {
return itemId;
}
private int quantity;
public void setItemId(long itemId) {
this.itemId = itemId;
}
private BigDecimal totalPrice;
public BigDecimal getPrice() {
return price;
}
public BigDecimal getDiscountAmount() {
return discountAmount;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setDiscountAmount(BigDecimal discountAmount) {
this.discountAmount = discountAmount;
}
public int getQuantity() {
return quantity;
}
public BigDecimal getDiscountPerc() {
return discountPerc;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public void setDiscountPerc(BigDecimal discountPerc) {
this.discountPerc = discountPerc;
}
public BigDecimal getShippingPrice() {
return shippingPrice;
}
public BigDecimal getHandlingPrice() {
return handlingPrice;
}
public void setShippingPrice(BigDecimal shippingPrice) {
this.shippingPrice = shippingPrice;
}
public void setHandlingPrice(BigDecimal handlingPrice) {
this.handlingPrice = handlingPrice;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public long getItemId() {
return itemId;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public void setItemId(long itemId) {
this.itemId = itemId;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public BigDecimal getShippingPrice() {
return shippingPrice;
}
public void setShippingPrice(BigDecimal shippingPrice) {
this.shippingPrice = shippingPrice;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
@Override
public String toString() {
@@ -134,4 +142,5 @@ public class LineItem {
return true;
}
}

View File

@@ -21,6 +21,7 @@ import java.util.Date;
import java.util.List;
public class Order {
public static final String LINE_ID_HEADER = "HEA";
public static final String LINE_ID_FOOTER = "FOT";
@@ -250,4 +251,5 @@ public class Order {
return true;
}
}

View File

@@ -16,8 +16,8 @@
package org.springframework.batch.sample.domain.order;
public class ShippingInfo {
public static final String LINE_ID_SHIPPING_INFO = "SIN";
private String shipperId;
@@ -99,4 +99,5 @@ public class ShippingInfo {
return true;
}
}

View File

@@ -33,9 +33,10 @@ import org.springframework.lang.Nullable;
/**
* @author peter.zozom
*
*
*/
public class OrderItemReader implements ItemReader<Order> {
private static Log log = LogFactory.getLog(OrderItemReader.class);
private Order order;
@@ -153,7 +154,7 @@ public class OrderItemReader implements ItemReader<Order> {
/**
* @param fieldSetReader reads lines from the file converting them to
* {@link FieldSet}.
* {@link FieldSet}.
*/
public void setFieldSetReader(ItemReader<FieldSet> fieldSetReader) {
this.fieldSetReader = fieldSetReader;

View File

@@ -24,7 +24,7 @@ import org.springframework.batch.sample.domain.order.Order;
/**
* Converts <code>Order</code> object to a list of strings.
*
*
* @author Dave Syer
* @author Dan Garrette
*/
@@ -54,9 +54,8 @@ public class OrderLineAggregator implements LineAggregator<Order> {
/**
* Set aggregators for all types of lines in the output file
*
* @param aggregators Map of LineAggregators used to map the various record types for
* each order
* each order
*/
public void setAggregators(Map<String, LineAggregator<Object>> aggregators) {
this.aggregators = aggregators;

View File

@@ -1,34 +1,34 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Address;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class AddressFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
Address address = order.getBillingAddress();
return new Object[] { "ADDRESS:", address.getAddrLine1(), address.getCity(), address.getZipCode() };
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Address;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class AddressFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
Address address = order.getBillingAddress();
return new Object[] { "ADDRESS:", address.getAddrLine1(), address.getCity(), address.getZipCode() };
}
}

View File

@@ -1,34 +1,34 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.BillingInfo;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class BillingInfoFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
BillingInfo billingInfo = order.getBilling();
return new Object[] { "BILLING:", billingInfo.getPaymentId(), billingInfo.getPaymentDesc() };
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.BillingInfo;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class BillingInfoFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
BillingInfo billingInfo = order.getBilling();
return new Object[] { "BILLING:", billingInfo.getPaymentId(), billingInfo.getPaymentDesc() };
}
}

View File

@@ -1,39 +1,39 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Customer;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class CustomerFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
Customer customer = order.getCustomer();
return new Object[] { "CUSTOMER:", customer.getRegistrationId(), emptyIfNull(customer.getFirstName()),
emptyIfNull(customer.getMiddleName()), emptyIfNull(customer.getLastName()) };
}
private String emptyIfNull(String s) {
return s != null ? s : "";
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Customer;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class CustomerFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
Customer customer = order.getCustomer();
return new Object[] { "CUSTOMER:", customer.getRegistrationId(), emptyIfNull(customer.getFirstName()),
emptyIfNull(customer.getMiddleName()), emptyIfNull(customer.getLastName()) };
}
private String emptyIfNull(String s) {
return s != null ? s : "";
}
}

View File

@@ -1,32 +1,32 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class FooterFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
return new Object[] { "END_ORDER:", order.getTotalPrice() };
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class FooterFieldExtractor implements FieldExtractor<Order> {
@Override
public Object[] extract(Order order) {
return new Object[] { "END_ORDER:", order.getTotalPrice() };
}
}

View File

@@ -1,34 +1,36 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import java.text.SimpleDateFormat;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class HeaderFieldExtractor implements FieldExtractor<Order> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
@Override
public Object[] extract(Order order) {
return new Object[] { "BEGIN_ORDER:", order.getOrderId(), dateFormat.format(order.getOrderDate()) };
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import java.text.SimpleDateFormat;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.Order;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class HeaderFieldExtractor implements FieldExtractor<Order> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
@Override
public Object[] extract(Order order) {
return new Object[] { "BEGIN_ORDER:", order.getOrderId(), dateFormat.format(order.getOrderDate()) };
}
}

View File

@@ -1,32 +1,32 @@
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.LineItem;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class LineItemFieldExtractor implements FieldExtractor<LineItem> {
@Override
public Object[] extract(LineItem item) {
return new Object[] { "ITEM:", item.getItemId(), item.getPrice() };
}
}
/*
* Copyright 2009-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.sample.domain.order.internal.extractor;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.sample.domain.order.LineItem;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class LineItemFieldExtractor implements FieldExtractor<LineItem> {
@Override
public Object[] extract(LineItem item) {
return new Object[] { "ITEM:", item.getItemId(), item.getPrice() };
}
}

View File

@@ -23,11 +23,17 @@ import org.springframework.batch.sample.domain.order.Address;
public class AddressFieldSetMapper implements FieldSetMapper<Address> {
public static final String ADDRESSEE_COLUMN = "ADDRESSEE";
public static final String ADDRESS_LINE1_COLUMN = "ADDR_LINE1";
public static final String ADDRESS_LINE2_COLUMN = "ADDR_LINE2";
public static final String CITY_COLUMN = "CITY";
public static final String ZIP_CODE_COLUMN = "ZIP_CODE";
public static final String STATE_COLUMN = "STATE";
public static final String COUNTRY_COLUMN = "COUNTRY";
@Override
@@ -44,4 +50,5 @@ public class AddressFieldSetMapper implements FieldSetMapper<Address> {
return address;
}
}

View File

@@ -23,6 +23,7 @@ import org.springframework.batch.sample.domain.order.BillingInfo;
public class BillingFieldSetMapper implements FieldSetMapper<BillingInfo> {
public static final String PAYMENT_TYPE_ID_COLUMN = "PAYMENT_TYPE_ID";
public static final String PAYMENT_DESC_COLUMN = "PAYMENT_DESC";
@Override
@@ -34,4 +35,5 @@ public class BillingFieldSetMapper implements FieldSetMapper<BillingInfo> {
return info;
}
}

View File

@@ -23,13 +23,21 @@ import org.springframework.batch.sample.domain.order.Customer;
public class CustomerFieldSetMapper implements FieldSetMapper<Customer> {
public static final String LINE_ID_COLUMN = "LINE_ID";
public static final String COMPANY_NAME_COLUMN = "COMPANY_NAME";
public static final String LAST_NAME_COLUMN = "LAST_NAME";
public static final String FIRST_NAME_COLUMN = "FIRST_NAME";
public static final String MIDDLE_NAME_COLUMN = "MIDDLE_NAME";
public static final String TRUE_SYMBOL = "T";
public static final String REGISTERED_COLUMN = "REGISTERED";
public static final String REG_ID_COLUMN = "REG_ID";
public static final String VIP_COLUMN = "VIP";
@Override
@@ -54,4 +62,5 @@ public class CustomerFieldSetMapper implements FieldSetMapper<Customer> {
return customer;
}
}

View File

@@ -23,6 +23,7 @@ import org.springframework.batch.sample.domain.order.Order;
public class HeaderFieldSetMapper implements FieldSetMapper<Order> {
public static final String ORDER_ID_COLUMN = "ORDER_ID";
public static final String ORDER_DATE_COLUMN = "ORDER_DATE";
@Override
@@ -33,4 +34,5 @@ public class HeaderFieldSetMapper implements FieldSetMapper<Order> {
return order;
}
}

View File

@@ -23,12 +23,19 @@ import org.springframework.batch.sample.domain.order.LineItem;
public class OrderItemFieldSetMapper implements FieldSetMapper<LineItem> {
public static final String TOTAL_PRICE_COLUMN = "TOTAL_PRICE";
public static final String QUANTITY_COLUMN = "QUANTITY";
public static final String HANDLING_PRICE_COLUMN = "HANDLING_PRICE";
public static final String SHIPPING_PRICE_COLUMN = "SHIPPING_PRICE";
public static final String DISCOUNT_AMOUNT_COLUMN = "DISCOUNT_AMOUNT";
public static final String DISCOUNT_PERC_COLUMN = "DISCOUNT_PERC";
public static final String PRICE_COLUMN = "PRICE";
public static final String ITEM_ID_COLUMN = "ITEM_ID";
@Override
@@ -46,4 +53,5 @@ public class OrderItemFieldSetMapper implements FieldSetMapper<LineItem> {
return item;
}
}

View File

@@ -23,7 +23,9 @@ import org.springframework.batch.sample.domain.order.ShippingInfo;
public class ShippingFieldSetMapper implements FieldSetMapper<ShippingInfo> {
public static final String ADDITIONAL_SHIPPING_INFO_COLUMN = "ADDITIONAL_SHIPPING_INFO";
public static final String SHIPPING_TYPE_ID_COLUMN = "SHIPPING_TYPE_ID";
public static final String SHIPPER_ID_COLUMN = "SHIPPER_ID";
@Override
@@ -36,4 +38,5 @@ public class ShippingFieldSetMapper implements FieldSetMapper<ShippingInfo> {
return info;
}
}

View File

@@ -34,13 +34,21 @@ import org.springframework.validation.Validator;
public class OrderValidator implements Validator {
private static final List<String> CARD_TYPES = new ArrayList<>();
private static final List<String> SHIPPER_IDS = new ArrayList<>();
private static final List<String> SHIPPER_TYPES = new ArrayList<>();
private static final long MAX_ID = 9999999999L;
private static final BigDecimal BD_MIN = new BigDecimal("0.0");
private static final BigDecimal BD_MAX = new BigDecimal("99999999.99");
private static final BigDecimal BD_PERC_MAX = new BigDecimal("100.0");
private static final int MAX_QUANTITY = 9999;
private static final BigDecimal BD_100 = new BigDecimal("100.00");
static {
@@ -71,11 +79,12 @@ public class OrderValidator implements Validator {
Order item = null;
try {
item = (Order) arg0;
} catch (ClassCastException cce) {
}
catch (ClassCastException cce) {
errors.reject("Incorrect type");
}
if(item != null) {
if (item != null) {
validateOrder(item, errors);
validateCustomer(item.getCustomer(), errors);
validateAddress(item.getBillingAddress(), errors, "billingAddress");
@@ -96,34 +105,45 @@ public class OrderValidator implements Validator {
boolean totalPrices = true;
for (LineItem lineItem : lineItems) {
if(lineItem.getItemId() <= 0 || lineItem.getItemId() > MAX_ID) {
if (lineItem.getItemId() <= 0 || lineItem.getItemId() > MAX_ID) {
ids = false;
}
if((BD_MIN.compareTo(lineItem.getPrice()) > 0) || (BD_MAX.compareTo(lineItem.getPrice()) < 0)) {
if ((BD_MIN.compareTo(lineItem.getPrice()) > 0) || (BD_MAX.compareTo(lineItem.getPrice()) < 0)) {
prices = false;
}
if (BD_MIN.compareTo(lineItem.getDiscountPerc()) != 0) {
//DiscountPerc must be between 0.0 and 100.0
// DiscountPerc must be between 0.0 and 100.0
if ((BD_MIN.compareTo(lineItem.getDiscountPerc()) > 0)
|| (BD_PERC_MAX.compareTo(lineItem.getDiscountPerc()) < 0)
|| (BD_MIN.compareTo(lineItem.getDiscountAmount()) != 0)) { //only one of DiscountAmount and DiscountPerc should be non-zero
|| (BD_MIN.compareTo(lineItem.getDiscountAmount()) != 0)) { // only
// one
// of
// DiscountAmount
// and
// DiscountPerc
// should
// be
// non-zero
discounts = false;
}
} else {
//DiscountAmount must be between 0.0 and item.price
}
else {
// DiscountAmount must be between 0.0 and item.price
if ((BD_MIN.compareTo(lineItem.getDiscountAmount()) > 0)
|| (lineItem.getPrice().compareTo(lineItem.getDiscountAmount()) < 0)) {
discounts = false;
}
}
if ((BD_MIN.compareTo(lineItem.getShippingPrice()) > 0) || (BD_MAX.compareTo(lineItem.getShippingPrice()) < 0)) {
if ((BD_MIN.compareTo(lineItem.getShippingPrice()) > 0)
|| (BD_MAX.compareTo(lineItem.getShippingPrice()) < 0)) {
shippingPrices = false;
}
if ((BD_MIN.compareTo(lineItem.getHandlingPrice()) > 0) || (BD_MAX.compareTo(lineItem.getHandlingPrice()) < 0)) {
if ((BD_MIN.compareTo(lineItem.getHandlingPrice()) > 0)
|| (BD_MAX.compareTo(lineItem.getHandlingPrice()) < 0)) {
handlingPrices = false;
}
@@ -131,33 +151,29 @@ public class OrderValidator implements Validator {
quantities = false;
}
if ((BD_MIN.compareTo(lineItem.getTotalPrice()) > 0)
|| (BD_MAX.compareTo(lineItem.getTotalPrice()) < 0)) {
if ((BD_MIN.compareTo(lineItem.getTotalPrice()) > 0) || (BD_MAX.compareTo(lineItem.getTotalPrice()) < 0)) {
totalPrices = false;
}
//calculate total price
// calculate total price
//discount coefficient = (100.00 - discountPerc) / 100.00
BigDecimal coef = BD_100.subtract(lineItem.getDiscountPerc())
.divide(BD_100, 4, RoundingMode.HALF_UP);
// discount coefficient = (100.00 - discountPerc) / 100.00
BigDecimal coef = BD_100.subtract(lineItem.getDiscountPerc()).divide(BD_100, 4, RoundingMode.HALF_UP);
//discountedPrice = (price * coefficient) - discountAmount
//at least one of discountPerc and discountAmount is 0 - this is validated by ValidateDiscountsFunction
BigDecimal discountedPrice = lineItem.getPrice().multiply(coef)
.subtract(lineItem.getDiscountAmount());
// discountedPrice = (price * coefficient) - discountAmount
// at least one of discountPerc and discountAmount is 0 - this is validated by
// ValidateDiscountsFunction
BigDecimal discountedPrice = lineItem.getPrice().multiply(coef).subtract(lineItem.getDiscountAmount());
//price for single item = discountedPrice + shipping + handling
// price for single item = discountedPrice + shipping + handling
BigDecimal singleItemPrice = discountedPrice.add(lineItem.getShippingPrice())
.add(lineItem.getHandlingPrice());
//total price = singleItemPrice * quantity
// total price = singleItemPrice * quantity
BigDecimal quantity = new BigDecimal(lineItem.getQuantity());
BigDecimal totalPrice = singleItemPrice.multiply(quantity)
.setScale(2, RoundingMode.HALF_UP);
BigDecimal totalPrice = singleItemPrice.multiply(quantity).setScale(2, RoundingMode.HALF_UP);
//calculatedPrice should equal to item.totalPrice
// calculatedPrice should equal to item.totalPrice
if (totalPrice.compareTo(lineItem.getTotalPrice()) != 0) {
totalPrices = false;
}
@@ -165,126 +181,132 @@ public class OrderValidator implements Validator {
String lineItemsFieldName = "lineItems";
if(!ids) {
if (!ids) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.id");
}
if(!prices) {
if (!prices) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.price");
}
if(!discounts) {
if (!discounts) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.discount");
}
if(!shippingPrices) {
if (!shippingPrices) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.shipping");
}
if(!handlingPrices) {
if (!handlingPrices) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.handling");
}
if(!quantities) {
if (!quantities) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.quantity");
}
if(!totalPrices) {
if (!totalPrices) {
errors.rejectValue(lineItemsFieldName, "error.lineitems.totalprice");
}
}
protected void validateShipping(ShippingInfo shipping, Errors errors) {
if(!SHIPPER_IDS.contains(shipping.getShipperId())) {
if (!SHIPPER_IDS.contains(shipping.getShipperId())) {
errors.rejectValue("shipping.shipperId", "error.shipping.shipper");
}
if(!SHIPPER_TYPES.contains(shipping.getShippingTypeId())) {
if (!SHIPPER_TYPES.contains(shipping.getShippingTypeId())) {
errors.rejectValue("shipping.shippingTypeId", "error.shipping.type");
}
if(StringUtils.hasText(shipping.getShippingInfo())) {
validateStringLength(shipping.getShippingInfo(), errors, "shipping.shippingInfo", "error.shipping.shippinginfo.length", 100);
if (StringUtils.hasText(shipping.getShippingInfo())) {
validateStringLength(shipping.getShippingInfo(), errors, "shipping.shippingInfo",
"error.shipping.shippinginfo.length", 100);
}
}
protected void validatePayment(BillingInfo billing, Errors errors) {
if(!CARD_TYPES.contains(billing.getPaymentId())) {
if (!CARD_TYPES.contains(billing.getPaymentId())) {
errors.rejectValue("billing.paymentId", "error.billing.type");
}
if(!billing.getPaymentDesc().matches("[A-Z]{4}-[0-9]{10,11}")) {
if (!billing.getPaymentDesc().matches("[A-Z]{4}-[0-9]{10,11}")) {
errors.rejectValue("billing.paymentDesc", "error.billing.desc");
}
}
protected void validateAddress(Address address, Errors errors,
String prefix) {
if(address != null) {
if(StringUtils.hasText(address.getAddressee())) {
validateStringLength(address.getAddressee(), errors, prefix + ".addressee", "error.baddress.addresse.length", 60);
protected void validateAddress(Address address, Errors errors, String prefix) {
if (address != null) {
if (StringUtils.hasText(address.getAddressee())) {
validateStringLength(address.getAddressee(), errors, prefix + ".addressee",
"error.baddress.addresse.length", 60);
}
validateStringLength(address.getAddrLine1(), errors, prefix + ".addrLine1", "error.baddress.addrline1.length", 50);
validateStringLength(address.getAddrLine1(), errors, prefix + ".addrLine1",
"error.baddress.addrline1.length", 50);
if(StringUtils.hasText(address.getAddrLine2())) {
validateStringLength(address.getAddrLine2(), errors, prefix + ".addrLine2", "error.baddress.addrline2.length", 50);
if (StringUtils.hasText(address.getAddrLine2())) {
validateStringLength(address.getAddrLine2(), errors, prefix + ".addrLine2",
"error.baddress.addrline2.length", 50);
}
validateStringLength(address.getCity(), errors, prefix + ".city", "error.baddress.city.length", 30);
validateStringLength(address.getZipCode(), errors, prefix + ".zipCode", "error.baddress.zipcode.length", 5);
if(StringUtils.hasText(address.getZipCode()) && !address.getZipCode().matches("[0-9]{5}")) {
if (StringUtils.hasText(address.getZipCode()) && !address.getZipCode().matches("[0-9]{5}")) {
errors.rejectValue(prefix + ".zipCode", "error.baddress.zipcode.format");
}
if((!StringUtils.hasText(address.getState()) && ("United States".equals(address.getCountry())) || StringUtils.hasText(address.getState()) && address.getState().length() != 2)) {
if ((!StringUtils.hasText(address.getState()) && ("United States".equals(address.getCountry()))
|| StringUtils.hasText(address.getState()) && address.getState().length() != 2)) {
errors.rejectValue(prefix + ".state", "error.baddress.state.length");
}
validateStringLength(address.getCountry(), errors, prefix + ".country", "error.baddress.country.length", 50);
validateStringLength(address.getCountry(), errors, prefix + ".country", "error.baddress.country.length",
50);
}
}
protected void validateStringLength(String string, Errors errors,
String field, String message, int length) {
if(!StringUtils.hasText(string) || string.length() > length) {
protected void validateStringLength(String string, Errors errors, String field, String message, int length) {
if (!StringUtils.hasText(string) || string.length() > length) {
errors.rejectValue(field, message);
}
}
protected void validateCustomer(Customer customer, Errors errors) {
if(!customer.isRegistered() && customer.isBusinessCustomer()) {
if (!customer.isRegistered() && customer.isBusinessCustomer()) {
errors.rejectValue("customer.registered", "error.customer.registration");
}
if(!StringUtils.hasText(customer.getCompanyName()) && customer.isBusinessCustomer()) {
if (!StringUtils.hasText(customer.getCompanyName()) && customer.isBusinessCustomer()) {
errors.rejectValue("customer.companyName", "error.customer.companyname");
}
if(!StringUtils.hasText(customer.getFirstName()) && !customer.isBusinessCustomer()) {
if (!StringUtils.hasText(customer.getFirstName()) && !customer.isBusinessCustomer()) {
errors.rejectValue("customer.firstName", "error.customer.firstname");
}
if(!StringUtils.hasText(customer.getLastName()) && !customer.isBusinessCustomer()) {
if (!StringUtils.hasText(customer.getLastName()) && !customer.isBusinessCustomer()) {
errors.rejectValue("customer.lastName", "error.customer.lastname");
}
if(customer.isRegistered() && (customer.getRegistrationId() < 0 || customer.getRegistrationId() >= 99999999L)) {
if (customer.isRegistered()
&& (customer.getRegistrationId() < 0 || customer.getRegistrationId() >= 99999999L)) {
errors.rejectValue("customer.registrationId", "error.customer.registrationid");
}
}
protected void validateOrder(Order item, Errors errors) {
if(item.getOrderId() < 0 || item.getOrderId() > 9999999999L) {
if (item.getOrderId() < 0 || item.getOrderId() > 9999999999L) {
errors.rejectValue("orderId", "error.order.id");
}
if(new Date().compareTo(item.getOrderDate()) < 0) {
if (new Date().compareTo(item.getOrderDate()) < 0) {
errors.rejectValue("orderDate", "error.order.date.future");
}
if(item.getLineItems() != null && item.getTotalLines() != item.getLineItems().size()) {
if (item.getLineItems() != null && item.getTotalLines() != item.getLineItems().size()) {
errors.rejectValue("totalLines", "error.order.lines.badcount");
}
}
}

View File

@@ -18,10 +18,11 @@ package org.springframework.batch.sample.domain.order.internal.xml;
/**
* An XML customer.
*
*
* This is a complex type.
*/
public class Customer {
private String name;
private String address;

View File

@@ -16,47 +16,51 @@
package org.springframework.batch.sample.domain.order.internal.xml;
/**
* An XML line-item.
*
* This is a complex type.
*/
public class LineItem {
private String description;
private double perUnitOunces;
private double price;
private int quantity;
public String getDescription() {
return description;
}
private String description;
public void setDescription(String description) {
this.description = description;
}
private double perUnitOunces;
public double getPerUnitOunces() {
return perUnitOunces;
}
private double price;
public void setPerUnitOunces(double perUnitOunces) {
this.perUnitOunces = perUnitOunces;
}
private int quantity;
public double getPrice() {
return price;
}
public String getDescription() {
return description;
}
public void setPrice(double price) {
this.price = price;
}
public void setDescription(String description) {
this.description = description;
}
public int getQuantity() {
return quantity;
}
public double getPerUnitOunces() {
return perUnitOunces;
}
public void setPerUnitOunces(double perUnitOunces) {
this.perUnitOunces = perUnitOunces;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}

View File

@@ -21,10 +21,11 @@ import java.util.List;
/**
* An XML order.
*
*
* This is a complex type.
*/
public class Order {
private Customer customer;
private Date date;

View File

@@ -16,29 +16,31 @@
package org.springframework.batch.sample.domain.order.internal.xml;
/**
* An XML shipper.
*
* This is a complex type.
*/
public class Shipper {
private String name;
private double perOunceRate;
public String getName() {
return name;
}
private String name;
public void setName(String name) {
this.name = name;
}
private double perOunceRate;
public double getPerOunceRate() {
return perOunceRate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPerOunceRate() {
return perOunceRate;
}
public void setPerOunceRate(double perOunceRate) {
this.perOunceRate = perOunceRate;
}
public void setPerOunceRate(double perOunceRate) {
this.perOunceRate = perOunceRate;
}
}

View File

@@ -16,13 +16,14 @@
package org.springframework.batch.sample.domain.person;
public class Child {
private String name;
public void setName(String name){
public void setName(String name) {
this.name = name;
}
public String getName(){
public String getName() {
return name;
}
@@ -66,4 +67,5 @@ public class Child {
return true;
}
}

View File

@@ -22,11 +22,17 @@ import java.util.List;
import org.springframework.batch.sample.domain.order.Address;
public class Person {
private String title = "";
private String firstName = "";
private String last_name = "";
private int age = 0;
private Address address = new Address();
private List<Child> children = new ArrayList<>();
public Person() {
@@ -206,4 +212,5 @@ public class Person {
return true;
}
}

View File

@@ -25,15 +25,17 @@ import org.springframework.batch.sample.domain.order.Address;
* Custom class that contains logic that would normally be be contained in
* {@link org.springframework.batch.item.ItemReader} and
* {@link org.springframework.batch.item.ItemWriter}.
*
*
* @author tomas.slanina
* @author Robert Kasanicky
* @author Mahmoud Ben Hassine
*/
public class PersonService {
private static final int GENERATION_LIMIT = 10;
private int generatedCounter = 0;
private int processedCounter = 0;
public Person getData() {
@@ -62,8 +64,8 @@ public class PersonService {
}
/*
* Badly designed method signature which accepts multiple implicitly related
* arguments instead of a single Person argument.
* Badly designed method signature which accepts multiple implicitly related arguments
* instead of a single Person argument.
*/
public void processPerson(String name, String city) {
processedCounter++;
@@ -76,4 +78,5 @@ public class PersonService {
public int getReceivedCount() {
return processedCounter;
}
}

View File

@@ -24,12 +24,14 @@ import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.sample.domain.person.Person;
public class PersonWriter implements ItemWriter<Person> {
private static Log log = LogFactory.getLog(PersonWriter.class);
@Override
private static Log log = LogFactory.getLog(PersonWriter.class);
@Override
public void write(List<? extends Person> data) {
if (log.isDebugEnabled()) {
log.debug("Processing: " + data);
}
}
if (log.isDebugEnabled()) {
log.debug("Processing: " + data);
}
}
}

View File

@@ -23,11 +23,11 @@ import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.lang.Nullable;
/**
* Composite {@link LineTokenizer} that delegates the tokenization of a line to one of two potential
* tokenizers. The file format in this case uses one character, either F, A, U, or D to indicate
* whether or not the line is an a footer record, or a customer add, update, or delete, and
* will delegate accordingly.
*
* Composite {@link LineTokenizer} that delegates the tokenization of a line to one of two
* potential tokenizers. The file format in this case uses one character, either F, A, U,
* or D to indicate whether or not the line is an a footer record, or a customer add,
* update, or delete, and will delegate accordingly.
*
* @author Lucas Ward
* @author Mahmoud Ben Hassine
* @since 2.0
@@ -35,62 +35,69 @@ import org.springframework.lang.Nullable;
public class CompositeCustomerUpdateLineTokenizer implements StepExecutionListener, LineTokenizer {
private LineTokenizer customerTokenizer;
private LineTokenizer footerTokenizer;
private StepExecution stepExecution;
/* (non-Javadoc)
* @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.String)
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.
* String)
*/
@Override
public FieldSet tokenize(@Nullable String line) {
if(line.charAt(0) == 'F'){
//line starts with F, so the footer tokenizer should tokenize it.
if (line.charAt(0) == 'F') {
// line starts with F, so the footer tokenizer should tokenize it.
FieldSet fs = footerTokenizer.tokenize(line);
long customerUpdateTotal = stepExecution.getReadCount();
long fileUpdateTotal = fs.readLong(1);
if(customerUpdateTotal != fileUpdateTotal){
throw new IllegalStateException("The total number of customer updates in the file footer does not match the " +
"number entered File footer total: [" + fileUpdateTotal + "] Total encountered during processing: [" +
customerUpdateTotal + "]");
if (customerUpdateTotal != fileUpdateTotal) {
throw new IllegalStateException(
"The total number of customer updates in the file footer does not match the "
+ "number entered File footer total: [" + fileUpdateTotal
+ "] Total encountered during processing: [" + customerUpdateTotal + "]");
}
else{
//return null, because the footer indicates an end of processing.
else {
// return null, because the footer indicates an end of processing.
return null;
}
}
else if(line.charAt(0) == 'A' || line.charAt(0) == 'U' || line.charAt(0) == 'D'){
//line starts with A,U, or D, so it must be a customer operation.
else if (line.charAt(0) == 'A' || line.charAt(0) == 'U' || line.charAt(0) == 'D') {
// line starts with A,U, or D, so it must be a customer operation.
return customerTokenizer.tokenize(line);
}
else{
//If the line doesn't start with any of the characters above, it must obviously be invalid.
else {
// If the line doesn't start with any of the characters above, it must
// obviously be invalid.
throw new IllegalArgumentException("Invalid line encountered for tokenizing: " + line);
}
}
@Override
public void beforeStep(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
/**
* Set the {@link LineTokenizer} that will be used to tokenize any lines that begin with
* A, U, or D, and are thus a customer operation.
*
* Set the {@link LineTokenizer} that will be used to tokenize any lines that begin
* with A, U, or D, and are thus a customer operation.
* @param customerTokenizer tokenizer to delegate to for customer operation records
*/
public void setCustomerTokenizer(LineTokenizer customerTokenizer) {
this.customerTokenizer = customerTokenizer;
}
/**
* Set the {@link LineTokenizer} that will be used to tokenize any lines that being with
* F and is thus a footer record.
*
* Set the {@link LineTokenizer} that will be used to tokenize any lines that being
* with F and is thus a footer record.
* @param footerTokenizer tokenizer to delegate to for footer records
*/
public void setFooterTokenizer(LineTokenizer footerTokenizer) {
this.footerTokenizer = footerTokenizer;
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.batch.sample.domain.trade;
/**
* Interface for writing customer's credit information to output.
*

View File

@@ -27,6 +27,7 @@ public interface CustomerDao {
CustomerCredit getCustomerByName(String name);
void insertCustomer(String name, BigDecimal credit);
void updateCustomer(String name, BigDecimal credit);
}

View File

@@ -18,39 +18,40 @@ package org.springframework.batch.sample.domain.trade;
import java.math.BigDecimal;
public class CustomerDebit {
private String name;
private BigDecimal debit;
public CustomerDebit() {
}
private String name;
CustomerDebit(String name, BigDecimal debit) {
this.name = name;
this.debit = debit;
}
private BigDecimal debit;
public BigDecimal getDebit() {
return debit;
}
public CustomerDebit() {
}
public void setDebit(BigDecimal debit) {
this.debit = debit;
}
CustomerDebit(String name, BigDecimal debit) {
this.name = name;
this.debit = debit;
}
public String getName() {
return name;
}
public BigDecimal getDebit() {
return debit;
}
public void setName(String name) {
this.name = name;
}
public void setDebit(BigDecimal debit) {
this.debit = debit;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "CustomerDebit [name=" + name + ", debit=" + debit + "]";
}
return "CustomerDebit [name=" + name + ", debit=" + debit + "]";
}
@Override
public int hashCode() {
@@ -92,4 +93,5 @@ public class CustomerDebit {
return true;
}
}

View File

@@ -16,13 +16,13 @@
package org.springframework.batch.sample.domain.trade;
/**
* Interface for writing {@link CustomerDebitDao} object to arbitrary output.
*
*
* @author Robert.Kasanicky
*/
public interface CustomerDebitDao {
void write(CustomerDebit customerDebit);
}

View File

@@ -20,39 +20,41 @@ import java.util.HashMap;
import java.util.Map;
/**
* Enum representing on of 3 possible actions on a customer update:
* Add, update, or delete
*
* Enum representing on of 3 possible actions on a customer update: Add, update, or delete
*
* @author Lucas Ward
*
*/
public enum CustomerOperation {
ADD('A'), UPDATE('U'), DELETE('D');
private final char code;
private static final Map<Character,CustomerOperation> CODE_MAP;
private static final Map<Character, CustomerOperation> CODE_MAP;
private CustomerOperation(char code) {
this.code = code;
}
static{
static {
CODE_MAP = new HashMap<>();
for(CustomerOperation operation:values()){
for (CustomerOperation operation : values()) {
CODE_MAP.put(operation.getCode(), operation);
}
}
public static CustomerOperation fromCode(char code){
if(CODE_MAP.containsKey(code)){
public static CustomerOperation fromCode(char code) {
if (CODE_MAP.containsKey(code)) {
return CODE_MAP.get(code);
}
else{
else {
throw new IllegalArgumentException("Invalid code: [" + code + "]");
}
}
public char getCode() {
return code;
}
}

View File

@@ -19,21 +19,24 @@ package org.springframework.batch.sample.domain.trade;
import java.math.BigDecimal;
/**
* Immutable Value Object representing an update to the customer as stored in the database.
* This object has the customer name, credit amount, and the operation to be performed
* on them. In the case of an add, a new customer will be entered with the appropriate
* credit. In the case of an update, the customer's credit is considered an absolute update.
* Deletes are currently not supported, but can still be read in from a file.
*
* Immutable Value Object representing an update to the customer as stored in the
* database. This object has the customer name, credit amount, and the operation to be
* performed on them. In the case of an add, a new customer will be entered with the
* appropriate credit. In the case of an update, the customer's credit is considered an
* absolute update. Deletes are currently not supported, but can still be read in from a
* file.
*
* @author Lucas Ward
* @since 2.0
*/
public class CustomerUpdate {
private final CustomerOperation operation;
private final String customerName;
private final BigDecimal credit;
public CustomerUpdate(CustomerOperation operation, String customerName, BigDecimal credit) {
this.operation = operation;
this.customerName = customerName;
@@ -51,9 +54,11 @@ public class CustomerUpdate {
public BigDecimal getCredit() {
return credit;
}
@Override
public String toString() {
return "Customer Update, name: [" + customerName + "], operation: [" + operation + "], credit: [" + credit + "]";
return "Customer Update, name: [" + customerName + "], operation: [" + operation + "], credit: [" + credit
+ "]";
}
}

View File

@@ -25,52 +25,53 @@ import org.springframework.lang.Nullable;
* @author Lucas Ward
*
*/
public class CustomerUpdateProcessor implements ItemProcessor<CustomerUpdate, CustomerUpdate>{
public class CustomerUpdateProcessor implements ItemProcessor<CustomerUpdate, CustomerUpdate> {
private CustomerDao customerDao;
private InvalidCustomerLogger invalidCustomerLogger;
@Nullable
@Override
public CustomerUpdate process(CustomerUpdate item) throws Exception {
if(item.getOperation() == DELETE){
//delete is not supported
if (item.getOperation() == DELETE) {
// delete is not supported
invalidCustomerLogger.log(item);
return null;
}
CustomerCredit customerCredit = customerDao.getCustomerByName(item.getCustomerName());
if(item.getOperation() == ADD && customerCredit == null){
if (item.getOperation() == ADD && customerCredit == null) {
return item;
}
else if(item.getOperation() == ADD && customerCredit != null){
//veto processing
else if (item.getOperation() == ADD && customerCredit != null) {
// veto processing
invalidCustomerLogger.log(item);
return null;
}
if(item.getOperation() == UPDATE && customerCredit != null){
if (item.getOperation() == UPDATE && customerCredit != null) {
return item;
}
else if(item.getOperation() == UPDATE && customerCredit == null){
//veto processing
else if (item.getOperation() == UPDATE && customerCredit == null) {
// veto processing
invalidCustomerLogger.log(item);
return null;
}
//if an item makes it through all these checks it can be assumed to be bad, logged, and skipped
// if an item makes it through all these checks it can be assumed to be bad,
// logged, and skipped
invalidCustomerLogger.log(item);
return null;
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public void setInvalidCustomerLogger(
InvalidCustomerLogger invalidCustomerLogger) {
public void setInvalidCustomerLogger(InvalidCustomerLogger invalidCustomerLogger) {
this.invalidCustomerLogger = invalidCustomerLogger;
}

View File

@@ -27,21 +27,21 @@ import org.springframework.batch.item.ItemWriter;
public class CustomerUpdateWriter implements ItemWriter<CustomerUpdate> {
private CustomerDao customerDao;
@Override
public void write(List<? extends CustomerUpdate> items) throws Exception {
for(CustomerUpdate customerUpdate : items){
if(customerUpdate.getOperation() == CustomerOperation.ADD){
for (CustomerUpdate customerUpdate : items) {
if (customerUpdate.getOperation() == CustomerOperation.ADD) {
customerDao.insertCustomer(customerUpdate.getCustomerName(), customerUpdate.getCredit());
}
else if(customerUpdate.getOperation() == CustomerOperation.UPDATE){
else if (customerUpdate.getOperation() == CustomerOperation.UPDATE) {
customerDao.updateCustomer(customerUpdate.getCustomerName(), customerUpdate.getCredit());
}
}
//flush and/or clear resources
// flush and/or clear resources
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}

View File

@@ -17,15 +17,14 @@
package org.springframework.batch.sample.domain.trade;
/**
* Interface for logging invalid customers. Customers may need to be logged because
* they already existed when attempted to be added. Or a non existent customer was
* updated.
*
* Interface for logging invalid customers. Customers may need to be logged because they
* already existed when attempted to be added. Or a non existent customer was updated.
*
* @author Lucas Ward
*
*/
public interface InvalidCustomerLogger {
void log(CustomerUpdate customerUpdate);
}

View File

@@ -19,41 +19,46 @@ package org.springframework.batch.sample.domain.trade;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author Rob Harrop
* @author Dave Syer
*/
@SuppressWarnings("serial")
public class Trade implements Serializable {
private String isin = "";
private long quantity = 0;
private BigDecimal price = BigDecimal.ZERO;
private String customer = "";
private String isin = "";
private long quantity = 0;
private BigDecimal price = BigDecimal.ZERO;
private String customer = "";
private Long id;
private long version = 0;
public Trade() {
}
public Trade(String isin, long quantity, BigDecimal price, String customer){
this.isin = isin;
this.quantity = quantity;
this.price = price;
this.customer = customer;
}
public Trade() {
}
/**
public Trade(String isin, long quantity, BigDecimal price, String customer) {
this.isin = isin;
this.quantity = quantity;
this.price = price;
this.customer = customer;
}
/**
* @param id id of the trade
*/
public Trade(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@@ -83,26 +88,26 @@ public class Trade implements Serializable {
}
public String getIsin() {
return isin;
}
return isin;
}
public BigDecimal getPrice() {
return price;
}
public BigDecimal getPrice() {
return price;
}
public long getQuantity() {
return quantity;
}
public long getQuantity() {
return quantity;
}
public String getCustomer() {
return customer;
}
public String getCustomer() {
return customer;
}
@Override
@Override
public String toString() {
return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price="
+ this.price + ",customer=" + this.customer + "]";
}
return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price=" + this.price + ",customer="
+ this.customer + "]";
}
@Override
public int hashCode() {
@@ -160,4 +165,5 @@ public class Trade implements Serializable {
}
return true;
}
}
}

View File

@@ -16,16 +16,16 @@
package org.springframework.batch.sample.domain.trade;
/**
* Interface for writing a Trade object to an arbitrary output.
*
*
* @author Robert Kasanicky
*/
public interface TradeDao {
/*
* Write a trade object to some kind of output, different implementations
* can write to file, database etc.
* Write a trade object to some kind of output, different implementations can write to
* file, database etc.
*/
void writeTrade(Trade trade);

View File

@@ -27,13 +27,18 @@ import org.springframework.batch.sample.domain.trade.InvalidCustomerLogger;
*
*/
public class CommonsLoggingInvalidCustomerLogger implements InvalidCustomerLogger {
protected static final Log LOG = LogFactory.getLog(CommandLineJobRunner.class);
/* (non-Javadoc)
* @see org.springframework.batch.sample.domain.trade.InvalidCustomerLogger#log(org.springframework.batch.sample.domain.trade.CustomerUpdate)
/*
* (non-Javadoc)
*
* @see org.springframework.batch.sample.domain.trade.InvalidCustomerLogger#log(org.
* springframework.batch.sample.domain.trade.CustomerUpdate)
*/
@Override
public void log(CustomerUpdate customerUpdate) {
LOG.error("invalid customer encountered: [ " + customerUpdate + "]");
}
}

View File

@@ -25,8 +25,11 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit;
* @since 2.0
*/
public class CustomerCreditFieldSetMapper implements FieldSetMapper<CustomerCredit> {
public static final int ID_COLUMN = 0;
public static final int NAME_COLUMN = 1;
public static final int CREDIT_COLUMN = 2;
@Override
@@ -38,4 +41,5 @@ public class CustomerCreditFieldSetMapper implements FieldSetMapper<CustomerCred
return trade;
}
}

View File

@@ -24,10 +24,11 @@ import org.springframework.lang.Nullable;
/**
* Increases customer's credit by a fixed amount.
*
*
* @author Robert Kasanicky
*/
public class CustomerCreditIncreaseProcessor implements ItemProcessor<CustomerCredit, CustomerCredit> {
public static final BigDecimal FIXED_AMOUNT = new BigDecimal("5");
@Nullable
@@ -35,4 +36,5 @@ public class CustomerCreditIncreaseProcessor implements ItemProcessor<CustomerCr
public CustomerCredit process(CustomerCredit item) throws Exception {
return item.increaseCreditBy(FIXED_AMOUNT);
}
}

View File

@@ -23,8 +23,8 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.batch.sample.domain.trade.CustomerCreditDao;
/**
* Delegates actual writing to a custom DAO.
*
* Delegates actual writing to a custom DAO.
*
* @author Robert Kasanicky
*/
public class CustomerCreditItemWriter implements ItemWriter<CustomerCredit> {

View File

@@ -23,20 +23,22 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.jdbc.core.RowMapper;
public class CustomerCreditRowMapper implements RowMapper<CustomerCredit> {
public static final String ID_COLUMN = "id";
public static final String NAME_COLUMN = "name";
public static final String CREDIT_COLUMN = "credit";
@Override
public CustomerCredit mapRow(ResultSet rs, int rowNum) throws SQLException {
CustomerCredit customerCredit = new CustomerCredit();
CustomerCredit customerCredit = new CustomerCredit();
customerCredit.setId(rs.getInt(ID_COLUMN));
customerCredit.setName(rs.getString(NAME_COLUMN));
customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN));
customerCredit.setId(rs.getInt(ID_COLUMN));
customerCredit.setName(rs.getString(NAME_COLUMN));
customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN));
return customerCredit;
return customerCredit;
}
}

View File

@@ -28,14 +28,20 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit;
*
*/
public class CustomerCreditUpdatePreparedStatementSetter implements ItemPreparedStatementSetter<CustomerCredit> {
public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000);
/* (non-Javadoc)
* @see org.springframework.batch.io.support.ItemPreparedStatementSetter#setValues(java.lang.Object, java.sql.PreparedStatement)
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.io.support.ItemPreparedStatementSetter#setValues(java.
* lang.Object, java.sql.PreparedStatement)
*/
@Override
public void setValues(CustomerCredit customerCredit, PreparedStatement ps) throws SQLException {
ps.setBigDecimal(1, customerCredit.getCredit().add(FIXED_AMOUNT));
ps.setLong(2, customerCredit.getId());
}
}

View File

@@ -23,6 +23,7 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.batch.sample.domain.trade.CustomerCreditDao;
public class CustomerCreditUpdateWriter implements ItemWriter<CustomerCredit> {
private double creditFilter = 800;
private CustomerCreditDao dao;
@@ -43,4 +44,5 @@ public class CustomerCreditUpdateWriter implements ItemWriter<CustomerCredit> {
public void setDao(CustomerCreditDao dao) {
this.dao = dao;
}
}

View File

@@ -22,20 +22,20 @@ import java.sql.SQLException;
import org.springframework.batch.sample.domain.trade.CustomerDebit;
import org.springframework.jdbc.core.RowMapper;
public class CustomerDebitRowMapper implements RowMapper<CustomerDebit> {
public static final String CUSTOMER_COLUMN = "customer";
public static final String PRICE_COLUMN = "price";
@Override
public CustomerDebit mapRow(ResultSet rs, int ignoredRowNumber)
throws SQLException {
CustomerDebit customerDebit = new CustomerDebit();
customerDebit.setName(rs.getString(CUSTOMER_COLUMN));
customerDebit.setDebit(rs.getBigDecimal(PRICE_COLUMN));
@Override
public CustomerDebit mapRow(ResultSet rs, int ignoredRowNumber) throws SQLException {
CustomerDebit customerDebit = new CustomerDebit();
customerDebit.setName(rs.getString(CUSTOMER_COLUMN));
customerDebit.setDebit(rs.getBigDecimal(PRICE_COLUMN));
return customerDebit;
}
return customerDebit;
}
}

View File

@@ -24,9 +24,8 @@ import org.springframework.batch.sample.domain.trade.CustomerDebitDao;
import org.springframework.batch.sample.domain.trade.Trade;
/**
* Transforms Trade to a CustomerDebit and asks DAO delegate to write the
* result.
*
* Transforms Trade to a CustomerDebit and asks DAO delegate to write the result.
*
* @author Robert Kasanicky
*/
public class CustomerUpdateWriter implements ItemWriter<Trade> {
@@ -46,4 +45,5 @@ public class CustomerUpdateWriter implements ItemWriter<Trade> {
public void setDao(CustomerDebitDao outputSource) {
this.dao = outputSource;
}
}

View File

@@ -31,8 +31,7 @@ import org.springframework.beans.factory.DisposableBean;
* @see CustomerCreditDao
* @author Robert Kasanicky
*/
public class FlatFileCustomerCreditDao implements CustomerCreditDao,
DisposableBean {
public class FlatFileCustomerCreditDao implements CustomerCreditDao, DisposableBean {
private ItemWriter<String> itemWriter;
@@ -47,8 +46,7 @@ public class FlatFileCustomerCreditDao implements CustomerCreditDao,
open(new ExecutionContext());
}
String line = "" + customerCredit.getName() + separator
+ customerCredit.getCredit();
String line = "" + customerCredit.getName() + separator + customerCredit.getCredit();
itemWriter.write(Collections.singletonList(line));
}

View File

@@ -24,13 +24,13 @@ import org.springframework.lang.Nullable;
/**
* Generates configurable number of {@link Trade} items.
*
*
* @author Robert Kasanicky
*/
public class GeneratingTradeItemReader implements ItemReader<Trade> {
private int limit = 1;
private int counter = 0;
@Nullable
@@ -38,18 +38,14 @@ public class GeneratingTradeItemReader implements ItemReader<Trade> {
public Trade read() throws Exception {
if (counter < limit) {
counter++;
return new Trade(
"isin" + counter,
counter,
new BigDecimal(counter),
"customer" + counter);
return new Trade("isin" + counter, counter, new BigDecimal(counter), "customer" + counter);
}
return null;
}
/**
* @param limit number of items that will be generated
* (null returned on consecutive calls).
* @param limit number of items that will be generated (null returned on consecutive
* calls).
*/
public void setLimit(int limit) {
this.limit = limit;
@@ -63,8 +59,8 @@ public class GeneratingTradeItemReader implements ItemReader<Trade> {
return limit;
}
public void resetCounter()
{
public void resetCounter() {
this.counter = 0;
}
}

View File

@@ -26,8 +26,8 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* Delegates writing to a custom DAO and flushes + clears hibernate session to
* fulfill the {@link ItemWriter} contract.
* Delegates writing to a custom DAO and flushes + clears hibernate session to fulfill the
* {@link ItemWriter} contract.
*
* @author Robert Kasanicky
* @author Michael Minella

View File

@@ -30,11 +30,12 @@ import org.springframework.batch.sample.domain.trade.CustomerCreditDao;
* @author Dave Syer
*
*/
public class HibernateCreditDao implements
CustomerCreditDao, RepeatListener {
public class HibernateCreditDao implements CustomerCreditDao, RepeatListener {
private int failOnFlush = -1;
private List<Throwable> errors = new ArrayList<>();
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
@@ -43,7 +44,6 @@ public class HibernateCreditDao implements
/**
* Public accessor for the errors property.
*
* @return the errors - a list of Throwable instances
*/
public List<Throwable> getErrors() {
@@ -53,7 +53,9 @@ public class HibernateCreditDao implements
/*
* (non-Javadoc)
*
* @see org.springframework.batch.sample.domain.trade.internal.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit)
* @see
* org.springframework.batch.sample.domain.trade.internal.CustomerCreditWriter#write(
* org.springframework.batch.sample.domain.CustomerCredit)
*/
@Override
public void writeCredit(CustomerCredit customerCredit) {
@@ -64,7 +66,8 @@ public class HibernateCreditDao implements
newCredit.setName(customerCredit.getName());
newCredit.setCredit(customerCredit.getCredit());
sessionFactory.getCurrentSession().save(newCredit);
} else {
}
else {
sessionFactory.getCurrentSession().update(customerCredit);
}
}
@@ -80,9 +83,7 @@ public class HibernateCreditDao implements
/**
* Public setter for the failOnFlush property.
*
* @param failOnFlush
* the ID of the record you want to fail on flush (for testing)
* @param failOnFlush the ID of the record you want to fail on flush (for testing)
*/
public void setFailOnFlush(int failOnFlush) {
this.failOnFlush = failOnFlush;
@@ -93,29 +94,45 @@ public class HibernateCreditDao implements
errors.add(e);
}
/* (non-Javadoc)
* @see org.springframework.batch.repeat.RepeatInterceptor#after(org.springframework.batch.repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus)
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.repeat.RepeatInterceptor#after(org.springframework.batch.
* repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus)
*/
@Override
public void after(RepeatContext context, RepeatStatus result) {
}
/* (non-Javadoc)
* @see org.springframework.batch.repeat.RepeatInterceptor#before(org.springframework.batch.repeat.RepeatContext)
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.repeat.RepeatInterceptor#before(org.springframework.batch
* .repeat.RepeatContext)
*/
@Override
public void before(RepeatContext context) {
}
/* (non-Javadoc)
* @see org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch.repeat.RepeatContext)
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch.
* repeat.RepeatContext)
*/
@Override
public void close(RepeatContext context) {
}
/* (non-Javadoc)
* @see org.springframework.batch.repeat.RepeatInterceptor#open(org.springframework.batch.repeat.RepeatContext)
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.repeat.RepeatInterceptor#open(org.springframework.batch.
* repeat.RepeatContext)
*/
@Override
public void open(RepeatContext context) {

View File

@@ -29,48 +29,49 @@ import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer
* @author Mahmoud Ben Hassine
*
*/
public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao{
public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao {
private static final String GET_CUSTOMER_BY_NAME = "SELECT ID, NAME, CREDIT from CUSTOMER where NAME = ?";
private static final String INSERT_CUSTOMER = "INSERT into CUSTOMER(ID, NAME, CREDIT) values(?,?,?)";
private static final String UPDATE_CUSTOMER = "UPDATE CUSTOMER set CREDIT = ? where NAME = ?";
private DataFieldMaxValueIncrementer incrementer;
public void setIncrementer(DataFieldMaxValueIncrementer incrementer) {
this.incrementer = incrementer;
}
@Override
public CustomerCredit getCustomerByName(String name) {
List<CustomerCredit> customers = getJdbcTemplate().query(GET_CUSTOMER_BY_NAME,
(rs, rowNum) -> {
CustomerCredit customer = new CustomerCredit();
customer.setName(rs.getString("NAME"));
customer.setId(rs.getInt("ID"));
customer.setCredit(rs.getBigDecimal("CREDIT"));
return customer;
}, name);
if(customers.size() == 0){
List<CustomerCredit> customers = getJdbcTemplate().query(GET_CUSTOMER_BY_NAME, (rs, rowNum) -> {
CustomerCredit customer = new CustomerCredit();
customer.setName(rs.getString("NAME"));
customer.setId(rs.getInt("ID"));
customer.setCredit(rs.getBigDecimal("CREDIT"));
return customer;
}, name);
if (customers.size() == 0) {
return null;
}
else{
else {
return customers.get(0);
}
}
@Override
public void insertCustomer(String name, BigDecimal credit) {
getJdbcTemplate().update(INSERT_CUSTOMER, new Object[]{incrementer.nextIntValue(), name, credit});
getJdbcTemplate().update(INSERT_CUSTOMER, new Object[] { incrementer.nextIntValue(), name, credit });
}
@Override
public void updateCustomer(String name, BigDecimal credit) {
getJdbcTemplate().update(UPDATE_CUSTOMER, new Object[]{credit, name});
getJdbcTemplate().update(UPDATE_CUSTOMER, new Object[] { credit, name });
}
}

View File

@@ -24,7 +24,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Reduces customer's credit by the provided amount.
*
@@ -32,18 +31,18 @@ import org.springframework.jdbc.core.JdbcTemplate;
*/
public class JdbcCustomerDebitDao implements CustomerDebitDao {
private static final String UPDATE_CREDIT = "UPDATE CUSTOMER SET credit= credit-? WHERE name=?";
private static final String UPDATE_CREDIT = "UPDATE CUSTOMER SET credit= credit-? WHERE name=?";
private JdbcOperations jdbcTemplate;
private JdbcOperations jdbcTemplate;
@Override
@Override
public void write(CustomerDebit customerDebit) {
jdbcTemplate.update(UPDATE_CREDIT, customerDebit.getDebit(), customerDebit.getName());
}
jdbcTemplate.update(UPDATE_CREDIT, customerDebit.getDebit(), customerDebit.getName());
}
@Autowired
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
}

View File

@@ -26,49 +26,49 @@ import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
/**
* Writes a Trade object to a database
*
* @author Robert Kasanicky
*/
public class JdbcTradeDao implements TradeDao {
private Log log = LogFactory.getLog(JdbcTradeDao.class);
/**
* template for inserting a row
*/
private static final String INSERT_TRADE_RECORD = "INSERT INTO TRADE (id, version, isin, quantity, price, customer) VALUES (?, 0, ?, ? ,?, ?)";
/**
* handles the processing of SQL query
*/
private JdbcOperations jdbcTemplate;
/**
* template for inserting a row
*/
private static final String INSERT_TRADE_RECORD = "INSERT INTO TRADE (id, version, isin, quantity, price, customer) VALUES (?, 0, ?, ? ,?, ?)";
/**
* database is not expected to be setup for auto increment
*/
private DataFieldMaxValueIncrementer incrementer;
/**
* handles the processing of SQL query
*/
private JdbcOperations jdbcTemplate;
/**
* @see TradeDao
*/
@Override
/**
* database is not expected to be setup for auto increment
*/
private DataFieldMaxValueIncrementer incrementer;
/**
* @see TradeDao
*/
@Override
public void writeTrade(Trade trade) {
Long id = incrementer.nextLongValue();
if (log.isDebugEnabled()) {
log.debug("Processing: " + trade);
}
jdbcTemplate.update(INSERT_TRADE_RECORD,
id, trade.getIsin(), trade.getQuantity(), trade.getPrice(),
Long id = incrementer.nextLongValue();
if (log.isDebugEnabled()) {
log.debug("Processing: " + trade);
}
jdbcTemplate.update(INSERT_TRADE_RECORD, id, trade.getIsin(), trade.getQuantity(), trade.getPrice(),
trade.getCustomer());
}
}
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void setIncrementer(DataFieldMaxValueIncrementer incrementer) {
this.incrementer = incrementer;
}
public void setIncrementer(DataFieldMaxValueIncrementer incrementer) {
this.incrementer = incrementer;
}
}

View File

@@ -20,24 +20,26 @@ import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.batch.sample.domain.trade.Trade;
public class TradeFieldSetMapper implements FieldSetMapper<Trade> {
public static final int ISIN_COLUMN = 0;
public static final int QUANTITY_COLUMN = 1;
public static final int PRICE_COLUMN = 2;
public static final int CUSTOMER_COLUMN = 3;
@Override
@Override
public Trade mapFieldSet(FieldSet fieldSet) {
Trade trade = new Trade();
trade.setIsin(fieldSet.readString(ISIN_COLUMN));
trade.setQuantity(fieldSet.readLong(QUANTITY_COLUMN));
trade.setPrice(fieldSet.readBigDecimal(PRICE_COLUMN));
trade.setCustomer(fieldSet.readString(CUSTOMER_COLUMN));
return trade;
}
Trade trade = new Trade();
trade.setIsin(fieldSet.readString(ISIN_COLUMN));
trade.setQuantity(fieldSet.readLong(QUANTITY_COLUMN));
trade.setPrice(fieldSet.readBigDecimal(PRICE_COLUMN));
trade.setCustomer(fieldSet.readString(CUSTOMER_COLUMN));
return trade;
}
}

View File

@@ -29,12 +29,11 @@ public class TradeProcessor implements ItemProcessor<Trade, Trade> {
private int failure = -1;
private int index = 0;
private Trade failedItem = null;
/**
* Public setter for the index on which failure should occur.
*
* @param failure the failure to set
*/
public void setValidationFailure(int failure) {
@@ -50,4 +49,5 @@ public class TradeProcessor implements ItemProcessor<Trade, Trade> {
}
return item;
}
}

View File

@@ -23,24 +23,29 @@ import org.springframework.batch.sample.domain.trade.Trade;
import org.springframework.jdbc.core.RowMapper;
public class TradeRowMapper implements RowMapper<Trade> {
public static final int ISIN_COLUMN = 1;
public static final int QUANTITY_COLUMN = 2;
public static final int PRICE_COLUMN = 3;
public static final int CUSTOMER_COLUMN = 4;
public static final int ID_COLUMN = 5;
public static final int VERSION_COLUMN = 6;
@Override
public Trade mapRow(ResultSet rs, int rowNum) throws SQLException {
Trade trade = new Trade(rs.getLong(ID_COLUMN));
trade.setIsin(rs.getString(ISIN_COLUMN));
trade.setQuantity(rs.getLong(QUANTITY_COLUMN));
trade.setPrice(rs.getBigDecimal(PRICE_COLUMN));
trade.setCustomer(rs.getString(CUSTOMER_COLUMN));
trade.setVersion(rs.getInt(VERSION_COLUMN));
return trade;
}

View File

@@ -32,8 +32,8 @@ import org.springframework.batch.sample.domain.trade.TradeDao;
import org.springframework.util.Assert;
/**
* Delegates the actual writing to custom DAO delegate. Allows configurable
* exception raising for testing skip and restart.
* Delegates the actual writing to custom DAO delegate. Allows configurable exception
* raising for testing skip and restart.
*/
public class TradeWriter extends ItemStreamSupport implements ItemWriter<Trade> {
@@ -56,7 +56,8 @@ public class TradeWriter extends ItemStreamSupport implements ItemWriter<Trade>
dao.writeTrade(trade);
Assert.notNull(trade.getPrice(), "price must not be null"); // There must be a price to total
Assert.notNull(trade.getPrice(), "price must not be null"); // There must be a
// price to total
if (this.failingCustomers.contains(trade.getCustomer())) {
throw new WriteFailedException("Something unexpected happened!");
@@ -100,10 +101,10 @@ public class TradeWriter extends ItemStreamSupport implements ItemWriter<Trade>
/**
* Public setter for the customers on which failure should occur.
*
* @param failingCustomers The customers to fail on
*/
public void setFailingCustomers(List<String> failingCustomers) {
this.failingCustomers = failingCustomers;
}
}

View File

@@ -23,17 +23,19 @@ import org.springframework.batch.sample.domain.trade.Trade;
* @author Michael Minella
*/
public class TradeValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return clazz.equals(Trade.class);
}
@Override
public void validate(Object target, Errors errors) {
Trade trade = (Trade) target;
@Override
public boolean supports(Class<?> clazz) {
return clazz.equals(Trade.class);
}
@Override
public void validate(Object target, Errors errors) {
Trade trade = (Trade) target;
if (trade.getIsin().length() >= 13) {
errors.rejectValue("isin", "isin_length");
}
}
if(trade.getIsin().length() >= 13) {
errors.rejectValue("isin", "isin_length");
}
}
}

View File

@@ -27,11 +27,13 @@ import org.springframework.jmx.export.notification.NotificationPublisherAware;
/**
* JMX notification broadcaster
*
*
* @author Dave Syer
* @since 1.0
*/
public class JobExecutionNotificationPublisher implements ApplicationListener<SimpleMessageApplicationEvent>, NotificationPublisherAware {
public class JobExecutionNotificationPublisher
implements ApplicationListener<SimpleMessageApplicationEvent>, NotificationPublisherAware {
private static final Log LOG = LogFactory.getLog(JobExecutionNotificationPublisher.class);
private NotificationPublisher notificationPublisher;
@@ -40,7 +42,7 @@ public class JobExecutionNotificationPublisher implements ApplicationListener<Si
/**
* Injection setter.
*
*
* @see org.springframework.jmx.export.notification.NotificationPublisherAware#setNotificationPublisher(org.springframework.jmx.export.notification.NotificationPublisher)
*/
@Override
@@ -49,11 +51,10 @@ public class JobExecutionNotificationPublisher implements ApplicationListener<Si
}
/**
* If the event is a {@link SimpleMessageApplicationEvent} for open and
* close we log the event at INFO level and send a JMX notification if we
* are also an MBean.
*
* @see ApplicationListener#onApplicationEvent(ApplicationEvent)
* If the event is a {@link SimpleMessageApplicationEvent} for open and close we log
* the event at INFO level and send a JMX notification if we are also an MBean.
*
* @see ApplicationListener#onApplicationEvent(ApplicationEvent)
*/
@Override
public void onApplicationEvent(SimpleMessageApplicationEvent applicationEvent) {
@@ -64,7 +65,6 @@ public class JobExecutionNotificationPublisher implements ApplicationListener<Si
/**
* Publish the provided message to an external listener if there is one.
*
* @param message the message to publish
*/
private void publish(String message) {
@@ -72,13 +72,13 @@ public class JobExecutionNotificationPublisher implements ApplicationListener<Si
Notification notification = new Notification("JobExecutionApplicationEvent", this, notificationCount++,
message);
/*
* We can't create a notification with a null source, but we can set
* it to null after creation(!). We want it to be null so that
* Spring will replace it automatically with the ObjectName (in
* ModelMBeanNotificationPublisher).
* We can't create a notification with a null source, but we can set it to
* null after creation(!). We want it to be null so that Spring will replace
* it automatically with the ObjectName (in ModelMBeanNotificationPublisher).
*/
notification.setSource(null);
notificationPublisher.sendNotification(notification);
}
}
}

View File

@@ -20,7 +20,7 @@ import org.springframework.context.ApplicationEvent;
/**
* @author Dave Syer
*
*
*/
@SuppressWarnings("serial")
public class SimpleMessageApplicationEvent extends ApplicationEvent {
@@ -31,13 +31,15 @@ public class SimpleMessageApplicationEvent extends ApplicationEvent {
super(source);
this.message = message;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see java.util.EventObject#toString()
*/
@Override
public String toString() {
return "message=["+message+"], " + super.toString();
return "message=[" + message + "], " + super.toString();
}
}

View File

@@ -22,9 +22,9 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
/**
* Wraps calls for methods taking {@link StepExecution} as an argument and
* publishes notifications in the form of {@link org.springframework.context.ApplicationEvent}.
*
* Wraps calls for methods taking {@link StepExecution} as an argument and publishes
* notifications in the form of {@link org.springframework.context.ApplicationEvent}.
*
* @author Dave Syer
*/
public class StepExecutionApplicationEventAdvice implements ApplicationEventPublisherAware {
@@ -33,7 +33,9 @@ public class StepExecutionApplicationEventAdvice implements ApplicationEventPubl
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)
*
* @see org.springframework.context.ApplicationEventPublisherAware#
* setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
@@ -51,15 +53,16 @@ public class StepExecutionApplicationEventAdvice implements ApplicationEventPubl
}
public void onError(JoinPoint jp, StepExecution stepExecution, Throwable t) {
String msg = "Error in: " + jp.toShortString() + " with: " + stepExecution + " (" + t.getClass() + ":" + t.getMessage() + ")";
String msg = "Error in: " + jp.toShortString() + " with: " + stepExecution + " (" + t.getClass() + ":"
+ t.getMessage() + ")";
publish(jp.getTarget(), msg);
}
/*
* Publish a {@link SimpleMessageApplicationEvent} with the given
* parameters.
* Publish a {@link SimpleMessageApplicationEvent} with the given parameters.
*/
private void publish(Object source, String message) {
applicationEventPublisher.publishEvent(new SimpleMessageApplicationEvent(source, message));
}
}

View File

@@ -17,19 +17,18 @@ package org.springframework.batch.sample.launch;
import java.util.Map;
/**
* @author Dave Syer
*
*
*/
public interface JobLoader {
void loadResource(String path);
Map<String, String> getConfigurations();
Object getJobConfiguration(String path);
Object getProperty(String path);
void setProperty(String path, String value);

View File

@@ -24,9 +24,8 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* This listener resets the count of its GeneratingTradeItemReader after the
* step.
*
* This listener resets the count of its GeneratingTradeItemReader after the step.
*
* @author Dan Garrette
* @author Mahmoud Ben Hassine
* @since 2.0
@@ -50,4 +49,5 @@ public class GeneratingTradeResettingListener implements StepExecutionListener,
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.reader, "The 'reader' must be set.");
}
}

Some files were not shown because too many files have changed in this diff Show More