Apply spring-javaformat style for consistency with other projects
Resolves #4118
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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() };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 : "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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() };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()) };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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() };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.batch.sample.domain.trade;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for writing customer's credit information to output.
|
||||
*
|
||||
|
||||
@@ -27,6 +27,7 @@ public interface CustomerDao {
|
||||
CustomerCredit getCustomerByName(String name);
|
||||
|
||||
void insertCustomer(String name, BigDecimal credit);
|
||||
|
||||
|
||||
void updateCustomer(String name, BigDecimal credit);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 + "]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user