OPEN - issue BATCH-788: Remove flush/clear from ItemWriter

Removed from transaction buffering writers (Jpa etc.)
This commit is contained in:
dsyer
2008-08-19 16:12:35 +00:00
parent a5080b772e
commit 9c287a9293
7 changed files with 155 additions and 549 deletions

View File

@@ -15,25 +15,26 @@
*/
package org.springframework.batch.item.database;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import junit.framework.TestCase;
import static org.easymock.EasyMock.*;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.context.RepeatContextSupport;
import org.springframework.batch.repeat.support.RepeatSynchronizationManager;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* @author Dave Syer
@@ -47,12 +48,11 @@ public class BatchSqlUpdateItemWriterTests extends TestCase {
protected List<Object> list = new ArrayList<Object>();
private RepeatContext context = new RepeatContextSupport(null);
private PreparedStatement ps;
/*
* (non-Javadoc)
*
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
@@ -75,25 +75,21 @@ public class BatchSqlUpdateItemWriterTests extends TestCase {
list.add(item);
}
});
TransactionSynchronizationManager.bindResource(writer.getResourceKey(), new HashSet<Object>(
Collections.singleton("spam")));
RepeatSynchronizationManager.register(context);
}
/*
* (non-Javadoc)
*
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
if (TransactionSynchronizationManager.hasResource(writer.getResourceKey())) {
TransactionSynchronizationManager.unbindResource(writer.getResourceKey());
}
RepeatSynchronizationManager.clear();
}
/**
* Test method for
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#afterPropertiesSet()}.
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#afterPropertiesSet()}
* .
* @throws Exception
*/
public void testAfterPropertiesSet() throws Exception {
@@ -109,83 +105,41 @@ public class BatchSqlUpdateItemWriterTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#write(List)}.
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#flush()}
* .
* @throws Exception
*/
public void testWrite() throws Exception {
writer.setSql("foo");
writer.write(Collections.singletonList("bar"));
// Nothing happens till we flush
assertEquals(0, list.size());
}
/**
* Test method for
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#clear()}.
*/
public void testClear() {
assertTrue(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
writer.clear();
assertFalse(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
}
/**
* Test method for
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#flush()}.
* @throws SQLException
*/
public void testFlush() throws SQLException {
assertTrue(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
ps.addBatch(); // there is one item in the buffer to start
expectLastCall().times(1);
expect(ps.executeBatch()).andReturn(new int[0]);
public void testWriteAndFlush() throws Exception {
ps.addBatch();
expectLastCall();
expect(ps.executeBatch()).andReturn(new int[] { 123 });
replay(ps);
writer.flush();
assertFalse(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
writer.write(Collections.singletonList("bar"));
assertEquals(2, list.size());
assertTrue(list.contains("SQL"));
}
/**
* Test method for
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#flush()}.
* @throws Exception
*/
public void testWriteAndFlush() throws Exception {
assertTrue(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
ps.addBatch();
expectLastCall().times(2);
expect(ps.executeBatch()).andReturn(new int[] { 123 });
replay(ps);
writer.write(Collections.singletonList("bar"));
writer.flush();
assertFalse(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
assertEquals(3, list.size());
assertTrue(list.contains("SQL"));
}
/**
* Test method for
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#flush()}.
* {@link org.springframework.batch.item.database.BatchSqlUpdateItemWriter#flush()}
* .
* @throws Exception
*/
public void testWriteAndFlushWithEmptyUpdate() throws Exception {
assertTrue(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
ps.addBatch();
expectLastCall().times(2);
expect(ps.executeBatch()).andReturn(new int[] {0});
expectLastCall();
expect(ps.executeBatch()).andReturn(new int[] { 0 });
replay(ps);
writer.write(Collections.singletonList("bar"));
try {
writer.flush();
writer.write(Collections.singletonList("bar"));
fail("Expected EmptyResultDataAccessException");
} catch (EmptyResultDataAccessException e) {
}
catch (EmptyResultDataAccessException e) {
// expected
String message = e.getMessage();
assertTrue("Wrong message: "+message, message.indexOf("did not update")>=0);
assertTrue("Wrong message: " + message, message.indexOf("did not update") >= 0);
}
assertFalse(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
assertEquals(3, list.size());
assertEquals(2, list.size());
assertTrue(list.contains("SQL"));
}
@@ -199,17 +153,15 @@ public class BatchSqlUpdateItemWriterTests extends TestCase {
});
ps.addBatch();
expectLastCall().times(1);
expect(ps.executeBatch()).andReturn(new int[] {123});
expect(ps.executeBatch()).andReturn(new int[] { 123 });
replay(ps);
writer.write(Collections.singletonList("foo"));
try {
writer.flush();
writer.write(Collections.singletonList("foo"));
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("bar", e.getMessage());
}
assertFalse(TransactionSynchronizationManager.hasResource(writer.getResourceKey()));
assertEquals(2, list.size());
writer.setItemPreparedStatementSetter(new ItemPreparedStatementSetter<String>() {
public void setValues(String item, PreparedStatement ps) throws SQLException {
@@ -217,21 +169,10 @@ public class BatchSqlUpdateItemWriterTests extends TestCase {
}
});
writer.write(Collections.singletonList("foo"));
writer.flush();
verify(ps);
assertEquals(4, list.size());
assertTrue(list.contains("SQL"));
assertTrue(list.contains("foo"));
assertTrue(context.isCompleteOnly());
}
/**
* Flushing without writing items previously should be handled gracefully.
*/
public void testEmptyFlush() {
// items are bound on write, so we unbind them first
TransactionSynchronizationManager.unbindResource(writer.getResourceKey());
writer.flush();
}
}

View File

@@ -21,14 +21,10 @@ import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.item.ClearFailedException;
import org.springframework.batch.item.FlushFailedException;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.context.RepeatContextSupport;
import org.springframework.batch.item.support.AbstractItemWriter;
import org.springframework.batch.repeat.support.RepeatSynchronizationManager;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* @author Dave Syer
@@ -40,30 +36,21 @@ public class HibernateAwareItemWriterTests extends TestCase {
public void flush() throws DataAccessException {
list.add("flush");
}
public void clear() {
list.add("clear");
list.add("clear");
};
}
private class StubItemWriter implements ItemWriter<Object> {
private class StubItemWriter extends AbstractItemWriter<Object> {
public void write(List<? extends Object> items) {
list.addAll(items);
}
public void clear() throws ClearFailedException {
list.add("delegateClear");
}
public void flush() throws FlushFailedException {
list.add("delegateFlush");
}
}
HibernateAwareItemWriter<Object> writer = new HibernateAwareItemWriter<Object>();
final List<Object> list = new ArrayList<Object>();
private RepeatContextSupport context;
final List<Object> list = new ArrayList<Object>();
/*
* (non-Javadoc)
@@ -72,26 +59,23 @@ public class HibernateAwareItemWriterTests extends TestCase {
*/
protected void setUp() throws Exception {
writer.setDelegate(new StubItemWriter());
context = new RepeatContextSupport(null);
RepeatSynchronizationManager.register(context);
writer.setHibernateTemplate(new HibernateTemplateWrapper());
list.clear();
}
/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
String key = writer.getResourceKey();
if (TransactionSynchronizationManager.hasResource(key)) {
TransactionSynchronizationManager.unbindResource(key);
}
RepeatSynchronizationManager.clear();
}
/**
* Test method for
* {@link org.springframework.batch.item.database.HibernateAwareItemWriter#afterPropertiesSet()}.
* {@link org.springframework.batch.item.database.HibernateAwareItemWriter#afterPropertiesSet()}
* .
*
* @throws Exception
*/
@@ -100,16 +84,17 @@ public class HibernateAwareItemWriterTests extends TestCase {
try {
writer.afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
catch (IllegalArgumentException e) {
// expected
assertTrue("Wrong message for exception: " + e.getMessage(), e
.getMessage().indexOf("delegate") >= 0);
assertTrue("Wrong message for exception: " + e.getMessage(), e.getMessage().indexOf("delegate") >= 0);
}
}
/**
* Test method for
* {@link org.springframework.batch.item.database.HibernateAwareItemWriter#afterPropertiesSet()}.
* {@link org.springframework.batch.item.database.HibernateAwareItemWriter#afterPropertiesSet()}
* .
*
* @throws Exception
*/
@@ -117,25 +102,12 @@ public class HibernateAwareItemWriterTests extends TestCase {
writer.afterPropertiesSet();
}
public void testWrite() throws Exception {
public void testWriteAndFlushSunnyDay() throws Exception {
writer.write(Collections.singletonList("foo"));
assertEquals(1, list.size());
assertEquals(3, list.size());
assertTrue(list.contains("foo"));
}
public void testFlushWithFailure() throws Exception{
final RuntimeException ex = new RuntimeException("bar");
writer.setHibernateTemplate(new HibernateTemplate() {
public void flush() throws DataAccessException {
throw ex;
}
});
try {
writer.flush();
fail("Expected RuntimeException");
} catch (RuntimeException e) {
assertEquals("bar", e.getMessage());
}
assertTrue(list.contains("flush"));
assertTrue(list.contains("clear"));
}
public void testWriteAndFlushWithFailure() throws Exception {
@@ -145,48 +117,24 @@ public class HibernateAwareItemWriterTests extends TestCase {
throw ex;
}
});
writer.write(Collections.singletonList("foo"));
try {
writer.flush();
writer.write(Collections.singletonList("foo"));
fail("Expected RuntimeException");
} catch (RuntimeException e) {
}
catch (RuntimeException e) {
assertEquals("bar", e.getMessage());
}
assertEquals(2, list.size());
assertTrue(list.contains("foo"));
assertTrue(list.contains("delegateFlush"));
writer.setHibernateTemplate(new HibernateTemplateWrapper() {
public void flush() throws DataAccessException {
list.add("flush");
}
});
writer.write(Collections.singletonList("foo"));
assertEquals(6, list.size());
System.err.println(list);
assertTrue(list.contains("flush"));
assertTrue(list.contains("clear"));
assertTrue(context.isCompleteOnly());
}
/**
* Test method for
* {@link org.springframework.batch.item.database.HibernateAwareItemWriter#flush()}.
*/
public void testFlush() throws Exception{
writer.flush();
assertEquals(3, list.size());
assertTrue(list.contains("flush"));
assertTrue(list.contains("clear"));
assertTrue(list.contains("delegateFlush"));
}
/**
* Test method for
* {@link org.springframework.batch.item.database.HibernateAwareItemWriter#clear()}.
*/
public void testClear() throws Exception{
writer.clear();
assertEquals(2, list.size());
assertTrue(list.contains("clear"));
assertTrue(list.contains("delegateClear"));
}
}

View File

@@ -16,30 +16,35 @@
package org.springframework.batch.item.database;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.batch.item.ItemWriter;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityManager;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
/**
* @author Thomas Risberg
*
*
*/
public class JpaAwareItemWriterTests {
JpaAwareItemWriter<Object> writer = new JpaAwareItemWriter<Object>();
ItemWriter<Object> delegate;
EntityManagerFactory emf;
@@ -47,10 +52,10 @@ public class JpaAwareItemWriterTests {
final List<Object> list = new ArrayList<Object>();
@Before
@SuppressWarnings({"unchecked"})
@SuppressWarnings( { "unchecked" })
public void setUp() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
TransactionSynchronizationManager.clearSynchronization();
}
delegate = createMock("delegate", ItemWriter.class);
writer.setDelegate(delegate);
@@ -64,49 +69,39 @@ public class JpaAwareItemWriterTests {
try {
writer.afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
catch (IllegalArgumentException e) {
// expected
assertTrue("Wrong message for exception: " + e.getMessage(), e
.getMessage().indexOf("delegate") >= 0);
assertTrue("Wrong message for exception: " + e.getMessage(), e.getMessage().indexOf("delegate") >= 0);
}
writer.setDelegate(delegate);
try {
writer.afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
catch (IllegalArgumentException e) {
// expected
assertTrue("Wrong message for exception: " + e.getMessage(), e
.getMessage().indexOf("EntityManagerFactory") >= 0);
assertTrue("Wrong message for exception: " + e.getMessage(),
e.getMessage().indexOf("EntityManagerFactory") >= 0);
}
}
@Test
public void testWrite() throws Exception {
delegate.write(Collections.singletonList("foo"));
replay(delegate);
writer.write(Collections.singletonList("foo"));
verify(delegate);
}
@Test
public void testFlushWithFailure() throws Exception{
final RuntimeException ex = new RuntimeException("bar");
public void testWriteAndFlushSunnyDay() throws Exception {
EntityManager em = createMock("em", EntityManager.class);
em.joinTransaction();
em.flush();
expectLastCall().andThrow(ex);
em.clear();
replay(em);
expect(emf.createEntityManager()).andReturn(em);
replay(emf);
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
delegate.flush();
List<String> items = Arrays.asList(new String[] { "foo", "spam" });
delegate.write(items);
replay(delegate);
try {
writer.flush();
fail("Expected RuntimeException");
} catch (RuntimeException e) {
assertEquals("bar", e.getMessage());
}
writer.write(items);
verify(delegate);
verify(em);
TransactionSynchronizationManager.unbindResource(emf);
}
@@ -116,65 +111,25 @@ public class JpaAwareItemWriterTests {
EntityManager em = createMock("em", EntityManager.class);
em.flush();
expectLastCall().andThrow(ex);
em.flush();
em.clear();
replay(em);
replay(emf);
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
delegate.write(Collections.singletonList("foo"));
delegate.flush();
delegate.write(Collections.singletonList("spam"));
delegate.flush();
List<String> items = Arrays.asList(new String[] { "foo", "spam" });
delegate.write(items);
replay(delegate);
writer.write(Collections.singletonList("foo"));
try {
writer.flush();
writer.write(items);
fail("Expected RuntimeException");
} catch (RuntimeException e) {
}
catch (RuntimeException e) {
assertEquals("bar", e.getMessage());
}
writer.write(Collections.singletonList("spam"));
writer.flush();
verify(delegate);
verify(em);
TransactionSynchronizationManager.unbindResource(emf);
}
@Test
public void testFlush() throws Exception{
EntityManager em = createMock("em", EntityManager.class);
em.flush();
em.clear();
replay(em);
replay(emf);
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
delegate.flush();
replay(delegate);
writer.flush();
verify(delegate);
verify(em);
TransactionSynchronizationManager.unbindResource(emf);
}
@Test
public void testClear() throws Exception{
EntityManager em = createMock("em", EntityManager.class);
em.clear();
replay(em);
replay(emf);
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
delegate.clear();
replay(delegate);
writer.clear();
verify(delegate);
verify(em);
TransactionSynchronizationManager.unbindResource(emf);
}
}