From a3675f0689c77bcdd433b324c5177bb1957a5457 Mon Sep 17 00:00:00 2001 From: Jonatan Kronqvist Date: Mon, 5 Sep 2011 11:19:34 +0000 Subject: [PATCH] Fix for #7186 - it is now possible to continue using the SQLContainer after an OptimisticLockException after first doing a rollback() svn changeset:20844/svn branch:6.7 --- .../data/util/sqlcontainer/SQLContainer.java | 24 ++++++++++ .../container/sqlcontainer/AllTests.java | 9 ++-- .../sqlcontainer/query/TableQueryTest.java | 44 +++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java index 8d00d6f495..f25252b8c0 100644 --- a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java +++ b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java @@ -414,6 +414,17 @@ public class SQLContainer implements Container, Container.Filterable, ee); } return false; + } catch (OptimisticLockException e) { + logger.log(Level.WARNING, "Failed to remove row, rolling back", + e); + try { + delegate.rollback(); + } catch (SQLException ee) { + /* Nothing can be done here */ + logger.log(Level.SEVERE, "Failed to rollback row removal", + ee); + } + throw e; } } else { removedItems.put((RowId) itemId, (RowItem) getItem(itemId)); @@ -460,6 +471,16 @@ public class SQLContainer implements Container, Container.Filterable, logger.log(Level.SEVERE, "Failed to roll back", ee); } return false; + } catch (OptimisticLockException e) { + logger.log(Level.WARNING, + "removeAllItems() failed, rolling back", e); + try { + delegate.rollback(); + } catch (SQLException ee) { + /* Nothing can be done here */ + logger.log(Level.SEVERE, "Failed to roll back", ee); + } + throw e; } } else { for (Object id : getItemIds()) { @@ -891,6 +912,9 @@ public class SQLContainer implements Container, Container.Filterable, } catch (SQLException e) { delegate.rollback(); throw e; + } catch (OptimisticLockException e) { + delegate.rollback(); + throw e; } } diff --git a/tests/src/com/vaadin/tests/server/container/sqlcontainer/AllTests.java b/tests/src/com/vaadin/tests/server/container/sqlcontainer/AllTests.java index f985fa2ad9..5191fcc341 100644 --- a/tests/src/com/vaadin/tests/server/container/sqlcontainer/AllTests.java +++ b/tests/src/com/vaadin/tests/server/container/sqlcontainer/AllTests.java @@ -19,12 +19,11 @@ import com.vaadin.tests.server.container.sqlcontainer.query.TableQueryTest; @RunWith(Suite.class) @SuiteClasses({ SimpleJDBCConnectionPoolTest.class, - J2EEConnectionPoolTest.class, LikeTest.class, - QueryBuilderTest.class, FreeformQueryTest.class, - RowIdTest.class, SQLContainerTest.class, + J2EEConnectionPoolTest.class, LikeTest.class, QueryBuilderTest.class, + FreeformQueryTest.class, RowIdTest.class, SQLContainerTest.class, SQLContainerTableQueryTest.class, ColumnPropertyTest.class, TableQueryTest.class, SQLGeneratorsTest.class, UtilTest.class, - TicketTests.class, BetweenTest.class, ReadOnlyRowIdTest.class}) + TicketTests.class, BetweenTest.class, ReadOnlyRowIdTest.class }) public class AllTests { /* Set the DB used for testing here! */ public enum DB { @@ -83,7 +82,7 @@ public class AllTests { versionStatements = new String[] { "create table VERSIONED (ID integer auto_increment not null, TEXT varchar(255), VERSION tinyint default 0, primary key(ID))", "CREATE TRIGGER upd_version BEFORE UPDATE ON VERSIONED" - + " FOR EACH ROW SET NEW.VERSION = @VERSION+1" }; + + " FOR EACH ROW SET NEW.VERSION = OLD.VERSION+1" }; break; case POSTGRESQL: offset = 1; diff --git a/tests/src/com/vaadin/tests/server/container/sqlcontainer/query/TableQueryTest.java b/tests/src/com/vaadin/tests/server/container/sqlcontainer/query/TableQueryTest.java index a3b2b20ffe..d6f5ce1cbc 100644 --- a/tests/src/com/vaadin/tests/server/container/sqlcontainer/query/TableQueryTest.java +++ b/tests/src/com/vaadin/tests/server/container/sqlcontainer/query/TableQueryTest.java @@ -616,4 +616,48 @@ public class TableQueryTest { container.commit(); } + @Test + public void removeRow_throwsOptimisticLockException_shouldStillWork() + throws SQLException { + if (AllTests.db == AllTests.DB.HSQLDB) { + // HSQLDB doesn't support versioning, so this is to make the test + // green. + return; + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "asdf"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + Object itemToRemove = container.firstItemId(); + try { + container.removeItem(itemToRemove); + container.commit(); + } catch (OptimisticLockException e) { + // This is expected, refresh and try again. + container.rollback(); + container.removeItem(itemToRemove); + container.commit(); + } + Object id = container.addItem(); + RowItem item = (RowItem) container.getItem(id); + item.getItemProperty("TEXT").setValue("foo"); + container.commit(); + } + } \ No newline at end of file -- 2.39.5