RESOLVED - issue BATCH-581: Add filter capability to item oriented paradigm

http://jira.springframework.org/browse/BATCH-581

Added a new sample job: 'CustomerFilterJob' that represents a use case for the filtering of items in a processor.
This commit is contained in:
lucasward
2008-09-29 05:29:29 +00:00
parent 97773129eb
commit 2bc0c17140
17 changed files with 885 additions and 1 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.0.6.v200806241357]]></pluginVersion>
<pluginVersion><![CDATA[2.1.0.v200808011800]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
@@ -42,6 +42,7 @@
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
<config>src/main/resources/jobs/taskletJob.xml</config>
<config>src/main/resources/jobs/headerFooterSample.xml</config>
<config>src/main/resources/jobs/customerFilterJob.xml</config>
</configs>
<configSets>
<configSet>
@@ -357,5 +358,17 @@
<config>src/main/resources/simple-job-launcher-context.xml</config>
</configs>
</configSet>
<configSet>
<name><![CDATA[customerFilterJob]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/resources/jobs/customerFilterJob.xml</config>
<config>src/main/resources/simple-job-launcher-context.xml</config>
<config>src/main/resources/data-source-context.xml</config>
<config>src/main/resources/data-source-context-init.xml</config>
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
</configs>
</configSet>
</configSets>
</beansProjectDescription>

View File

@@ -0,0 +1,61 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import org.springframework.batch.item.file.mapping.FieldSet;
import org.springframework.batch.item.file.transform.LineTokenizer;
/**
* 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
* @since 2.0
*/
public class CompositeCustomerUpdateLineTokenizer implements LineTokenizer {
private LineTokenizer customerTokenizer;
private LineTokenizer footerTokenizer;
/* (non-Javadoc)
* @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.String)
*/
public FieldSet tokenize(String line) {
if(line.charAt(0) == 'F'){
//line starts with F, so the footer tokenizer should tokenize it.
return footerTokenizer.tokenize(line);
}
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.
throw new IllegalArgumentException("Invalid line encountered for tokenizing: " + line);
}
}
/**
* 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
*/
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.
*
* @param footerTokenizer
*/
public void setFooterTokenizer(LineTokenizer footerTokenizer) {
this.footerTokenizer = footerTokenizer;
}
}

View File

@@ -0,0 +1,19 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import java.math.BigDecimal;
/**
* @author Lucas Ward
*
*/
public interface CustomerDao {
CustomerCredit getCustomerByName(String name);
void insertCustomer(String name, BigDecimal credit);
void updateCustomer(String name, BigDecimal credit);
}

View File

@@ -0,0 +1,45 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import java.util.HashMap;
import java.util.Map;
/**
* 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> codeMap;
private CustomerOperation(char code) {
this.code = code;
}
static{
codeMap = new HashMap<Character,CustomerOperation>();
for(CustomerOperation operation:values()){
codeMap.put(operation.getCode(), operation);
}
}
public static CustomerOperation fromCode(char code){
if(codeMap.containsKey(code)){
return codeMap.get(code);
}
else{
throw new IllegalArgumentException("Invalid code: [" + code + "]");
}
}
public char getCode() {
return code;
}
}

View File

@@ -0,0 +1,46 @@
/**
*
*/
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 ammount, 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;
this.credit = credit;
}
public CustomerOperation getOperation() {
return operation;
}
public String getCustomerName() {
return customerName;
}
public BigDecimal getCredit() {
return credit;
}
@Override
public String toString() {
return "Customer Update, name: [" + customerName + "], operation: [" + operation + "], credit: [" + credit + "]";
}
}

View File

@@ -0,0 +1,52 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import java.math.BigDecimal;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.item.file.mapping.FieldSet;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
/**
* {@link FieldSetMapper} for mapping the
*
* @author Lucas Ward
*
*/
public class CustomerUpdateFieldSetMapper extends StepExecutionListenerSupport implements FieldSetMapper<CustomerUpdate> {
StepExecution stepExecution;
public CustomerUpdate mapLine(FieldSet fs) {
char code = fs.readChar(0);
if(code == 'F'){
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 + "]");
}
else{
//return null, because the footer indicates an end of processing.
return null;
}
}
CustomerOperation operation = CustomerOperation.fromCode(code);
String name = fs.readString(1);
BigDecimal credit = fs.readBigDecimal(2);
return new CustomerUpdate(operation, name, credit);
}
@Override
public void beforeStep(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}

View File

@@ -0,0 +1,61 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import static org.springframework.batch.sample.domain.trade.CustomerOperation.*;
import org.springframework.batch.item.ItemProcessor;
/**
* @author Lucas Ward
*
*/
public class CustomerUpdateProcessor implements ItemProcessor<CustomerUpdate, CustomerUpdate>{
CustomerDao customerDao;
InvalidCustomerLogger invalidCustomerLogger;
public CustomerUpdate process(CustomerUpdate item) throws Exception {
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){
return item;
}
else if(item.getOperation() == ADD && customerCredit != null){
//veto processing
invalidCustomerLogger.log(item);
return null;
}
if(item.getOperation() == UPDATE && customerCredit != null){
return item;
}
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
invalidCustomerLogger.log(item);
return null;
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public void setInvalidCustomerLogger(
InvalidCustomerLogger invalidCustomerLogger) {
this.invalidCustomerLogger = invalidCustomerLogger;
}
}

View File

@@ -0,0 +1,33 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
/**
* @author Lucas Wward
*
*/
public class CustomerUpdateWriter implements ItemWriter<CustomerUpdate> {
private CustomerDao customerDao;
public void write(List<? extends CustomerUpdate> items) throws Exception {
for(CustomerUpdate customerUpdate : items){
if(customerUpdate.getOperation() == CustomerOperation.ADD){
customerDao.insertCustomer(customerUpdate.getCustomerName(), customerUpdate.getCredit());
}
else if(customerUpdate.getOperation() == CustomerOperation.UPDATE){
customerDao.updateCustomer(customerUpdate.getCustomerName(), customerUpdate.getCredit());
}
}
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
}

View File

@@ -0,0 +1,18 @@
/**
*
*/
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.
*
* @author Lucas Ward
*
*/
public interface InvalidCustomerLogger {
void log(CustomerUpdate customerUpdate);
}

View File

@@ -0,0 +1,28 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.launch.support.CommandLineJobRunner;
import org.springframework.batch.sample.domain.trade.CustomerUpdate;
import org.springframework.batch.sample.domain.trade.InvalidCustomerLogger;
/**
* @author Lucas Ward
*
*/
public class CommonsLoggingInvalidCustomerLogger implements
InvalidCustomerLogger {
protected static final Log logger = LogFactory.getLog(CommandLineJobRunner.class);
/* (non-Javadoc)
* @see org.springframework.batch.sample.domain.trade.InvalidCustomerLogger#log(org.springframework.batch.sample.domain.trade.CustomerUpdate)
*/
public void log(CustomerUpdate customerUpdate) {
logger.error("invalid customer encountered: [ " + customerUpdate + "]");
}
}

View File

@@ -0,0 +1,61 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade.internal;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.batch.sample.domain.trade.CustomerDao;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* @author Lucas Ward
*
*/
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(NAME, CREDIT) values(?,?)";
private static final String UPDATE_CUSTOMER = "UPDATE CUSTOMER set CREDIT = ? where NAME = ?";
public CustomerCredit getCustomerByName(String name) {
@SuppressWarnings("unchecked")
List<CustomerCredit> customers = (List<CustomerCredit>) getJdbcTemplate().query(GET_CUSTOMER_BY_NAME, new Object[]{name},
new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
CustomerCredit customer = new CustomerCredit();
customer.setName(rs.getString("NAME"));
customer.setId(rs.getInt("ID"));
customer.setCredit(rs.getBigDecimal("CREDIT"));
return customer;
}
});
if(customers.size() == 0){
return null;
}
else{
return customers.get(0);
}
}
public void insertCustomer(String name, BigDecimal credit) {
getJdbcTemplate().update(INSERT_CUSTOMER, new Object[]{name, credit});
}
public void updateCustomer(String name, BigDecimal credit) {
getJdbcTemplate().update(UPDATE_CUSTOMER, new Object[]{credit, name});
}
}

View File

@@ -0,0 +1,6 @@
SCust Credit
Acustomer5 00032345
Ucustomer3 00100500
Acustomer6 00123456
Dcustomer1 00000000
F0000004

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<bean name="customerFilterJob" parent="simpleJob">
<property name="steps">
<list>
<bean name="uploadCustomer" parent="skipLimitStep">
<property name="itemReader" ref="customerFileUploadReader" />
<property name="itemProcessor">
<bean class="org.springframework.batch.sample.domain.trade.CustomerUpdateProcessor" >
<property name="customerDao" ref="customerDao" />
<property name="invalidCustomerLogger" >
<bean class="org.springframework.batch.sample.domain.trade.internal.CommonsLoggingInvalidCustomerLogger" />
</property>
</bean>
</property>
<property name="itemWriter" >
<bean class="org.springframework.batch.sample.domain.trade.CustomerUpdateWriter" >
<property name="customerDao" ref="customerDao" />
</bean>
</property>
<property name="listeners" ref="customerMapper" />
</bean>
</list>
</property>
</bean>
<bean name="customerFileUploadReader" class="org.springframework.batch.item.file.FlatFileItemReader" >
<property name="resource" ref="customerFileResource" />
<property name="lineTokenizer" ref="customerTokenizer" />
<property name="linesToSkip" value="1" />
<property name="fieldSetMapper" ref="customerMapper" />
</bean>
<bean name="customerMapper" class="org.springframework.batch.sample.domain.trade.CustomerUpdateFieldSetMapper" />
<bean name="customerTokenizer" class="org.springframework.batch.sample.domain.trade.CompositeCustomerUpdateLineTokenizer" >
<property name="customerTokenizer">
<bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer" >
<property name="columns" value="1,2-18,19-26" />
</bean>
</property>
<property name="footerTokenizer" >
<bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
<property name="columns" value="1,2-8" />
</bean>
</property>
</bean>
<bean name="customerDao" class="org.springframework.batch.sample.domain.trade.internal.JdbcCustomerDao" >
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="customerFileResource" class="org.springframework.core.io.ClassPathResource" >
<constructor-arg value="data/customerFilterJob/input/customers.txt" />
</bean>
</beans>

View File

@@ -0,0 +1,187 @@
/*
* Copyright 2006-2007 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
*
* http://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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration()
public class CustomerFilterJobFunctionalTests extends AbstractValidatingBatchLauncherTests {
private static final String GET_CUSTOMERS = "select NAME, CREDIT from CUSTOMER order by NAME";
private List<Customer> customers;
private int activeRow = 0;
private SimpleJdbcTemplate simpleJdbcTemplate;
private Map<String, Double> credits = new HashMap<String, Double>();
@Autowired
public void setDataSource(DataSource dataSource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
@Before
public void onSetUp() throws Exception {
simpleJdbcTemplate.update("delete from TRADE");
List<Map<String, Object>> list = simpleJdbcTemplate.queryForList("select name, CREDIT from customer");
for (Map<String, Object> map : list) {
credits.put((String) map.get("NAME"), ((Number) map.get("CREDIT")).doubleValue());
}
}
@After
public void tearDown() throws Exception {
simpleJdbcTemplate.update("delete from TRADE");
}
@Test
public void testLaunchJob() throws Exception{
super.testLaunchJob();
}
protected void validatePostConditions() {
// assertTrue(((Resource)applicationContext.getBean("customerFileLocator")).exists());
customers = Arrays.asList(new Customer("customer1", (credits.get("customer1") )),
new Customer("customer2", (credits.get("customer2"))),
new Customer("customer3", 100500),
new Customer("customer4", credits.get("customer4")),
new Customer("customer5", 32345),
new Customer("customer6", 123456));
// check content of the customer table
activeRow = 0;
simpleJdbcTemplate.getJdbcOperations().query(GET_CUSTOMERS, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
Customer customer = customers.get(activeRow++);
assertEquals(customer.getName(),rs.getString(1));
assertEquals(customer.getCredit(), rs.getDouble(2), .01);
}
});
assertEquals(customers.size(), activeRow);
// check content of the output file
}
protected void validatePreConditions() {
assertTrue(((Resource)applicationContext.getBean("customerFileResource")).exists());
}
private static class Customer {
private String name;
private double credit;
public Customer(String name, double credit) {
this.name = name;
this.credit = credit;
}
public Customer(){
}
/**
* @return the credit
*/
public double getCredit() {
return credit;
}
/**
* @param credit the credit to set
*/
public void setCredit(double credit) {
this.credit = credit;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
final int PRIME = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(credit);
result = PRIME * result + (int) (temp ^ (temp >>> 32));
result = PRIME * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Customer other = (Customer) obj;
if (Double.doubleToLongBits(credit) != Double.doubleToLongBits(other.credit))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
}

View File

@@ -0,0 +1,97 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.item.file.mapping.DefaultFieldSet;
import org.springframework.batch.item.file.mapping.FieldSet;
import org.springframework.batch.item.file.transform.LineTokenizer;
/**
* @author Lucas Ward
*
*/
public class CompositeCustomerUpdateLineTokenizerTests {
StubLineTokenizer customerTokenizer;
FieldSet customerFieldSet = new DefaultFieldSet(null);
StubLineTokenizer footerTokenizer;
FieldSet footerFieldSet = new DefaultFieldSet(null);
CompositeCustomerUpdateLineTokenizer compositeTokenizer;
@Before
public void init(){
customerTokenizer = new StubLineTokenizer(customerFieldSet);
footerTokenizer = new StubLineTokenizer(footerFieldSet);
compositeTokenizer = new CompositeCustomerUpdateLineTokenizer();
compositeTokenizer.setCustomerTokenizer(customerTokenizer);
compositeTokenizer.setFooterTokenizer(footerTokenizer);
}
@Test
public void testFooter(){
String footerLine = "Ffjkdalsfjdaskl;f";
FieldSet fs = compositeTokenizer.tokenize(footerLine);
assertEquals(footerFieldSet, fs);
assertEquals(footerLine, footerTokenizer.getTokenizedLine());
}
@Test
public void testCustomerAdd(){
String customerAddLine = "AFDASFDASFDFSA";
FieldSet fs = compositeTokenizer.tokenize(customerAddLine);
assertEquals(customerFieldSet, fs);
assertEquals(customerAddLine, customerTokenizer.getTokenizedLine());
}
@Test
public void testCustomerDelete(){
String customerAddLine = "DFDASFDASFDFSA";
FieldSet fs = compositeTokenizer.tokenize(customerAddLine);
assertEquals(customerFieldSet, fs);
assertEquals(customerAddLine, customerTokenizer.getTokenizedLine());
}
@Test
public void testCustomerUpdate(){
String customerAddLine = "UFDASFDASFDFSA";
FieldSet fs = compositeTokenizer.tokenize(customerAddLine);
assertEquals(customerFieldSet, fs);
assertEquals(customerAddLine, customerTokenizer.getTokenizedLine());
}
@Test(expected=IllegalArgumentException.class)
public void testInvalidLine(){
String invalidLine = "INVALID";
compositeTokenizer.tokenize(invalidLine);
}
private static class StubLineTokenizer implements LineTokenizer{
private final FieldSet fieldSetToReturn;
private String tokenizedLine;
public StubLineTokenizer(FieldSet fieldSetToReturn) {
this.fieldSetToReturn = fieldSetToReturn;
}
public FieldSet tokenize(String line) {
this.tokenizedLine = line;
return fieldSetToReturn;
}
public String getTokenizedLine() {
return tokenizedLine;
}
}
}

View File

@@ -0,0 +1,86 @@
/**
*
*/
package org.springframework.batch.sample.domain.trade;
import static org.easymock.EasyMock.*;
import static org.springframework.batch.sample.domain.trade.CustomerOperation.*;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import org.junit.Before;
import org.junit.Test;
/**
* @author Lucas Ward
*
*/
public class CustomerUpdateProcessorTests {
CustomerDao customerDao;
InvalidCustomerLogger logger;
CustomerUpdateProcessor processor;
@Before
public void init(){
customerDao = createMock(CustomerDao.class);
logger = createMock(InvalidCustomerLogger.class);
processor = new CustomerUpdateProcessor();
processor.setCustomerDao(customerDao);
processor.setInvalidCustomerLogger(logger);
}
@Test
public void testSuccessfulAdd() throws Exception{
CustomerUpdate customerUpdate = new CustomerUpdate(ADD, "test customer", new BigDecimal(232.2));
expect(customerDao.getCustomerByName("test customer")).andReturn(null);
replay(customerDao);
assertEquals(customerUpdate, processor.process(customerUpdate));
verify(customerDao);
}
@Test
public void testInvalidAdd() throws Exception{
CustomerUpdate customerUpdate = new CustomerUpdate(ADD, "test customer", new BigDecimal(232.2));
expect(customerDao.getCustomerByName("test customer")).andReturn(new CustomerCredit());
logger.log(customerUpdate);
replay(customerDao, logger);
assertNull("Processor should return null", processor.process(customerUpdate));
verify(customerDao, logger);
}
@Test
public void testDelete() throws Exception{
//delete should never work, therefore, ensure it fails fast.
CustomerUpdate customerUpdate = new CustomerUpdate(DELETE, "test customer", new BigDecimal(232.2));
logger.log(customerUpdate);
replay(customerDao, logger);
assertNull("Processor should return null", processor.process(customerUpdate));
verify(customerDao, logger);
}
@Test
public void testSuccessfulUpdate() throws Exception{
CustomerUpdate customerUpdate = new CustomerUpdate(UPDATE, "test customer", new BigDecimal(232.2));
expect(customerDao.getCustomerByName("test customer")).andReturn(new CustomerCredit());
replay(customerDao, logger);
assertEquals(customerUpdate, processor.process(customerUpdate));
verify(customerDao, logger);
}
@Test
public void testInvalidUpdate() throws Exception{
CustomerUpdate customerUpdate = new CustomerUpdate(UPDATE, "test customer", new BigDecimal(232.2));
expect(customerDao.getCustomerByName("test customer")).andReturn(null);
logger.log(customerUpdate);
replay(customerDao, logger);
assertNull("Processor should return null", processor.process(customerUpdate));
verify(customerDao, logger);
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<import resource="classpath:/simple-job-launcher-context.xml" />
<import resource="classpath:/jobs/customerFilterJob.xml" />
</beans>