@Test public void shouldBeAbleToAccessExceptionThrownInEventHook() { class MyFancyException extends Exception {} ExceptionThrowingEventHandler handler = new ExceptionThrowingEventHandler(new MyFancyException(), null, null); GraphDatabaseService db = dbRule.getGraphDatabaseService(); db.registerTransactionEventHandler(handler); try { Transaction tx = db.beginTx(); try { db.createNode().delete(); tx.success(); tx.close(); fail("Should fail commit"); } catch (TransactionFailureException e) { Throwable currentEx = e; do { currentEx = currentEx.getCause(); if (currentEx instanceof MyFancyException) { return; } } while (currentEx.getCause() != null); fail( "Expected to find the exception thrown in the event hook as the cause of transaction failure."); } } finally { db.unregisterTransactionEventHandler(handler); } }
@Test public void shouldAccessAssignedLabels() throws Exception { // given GraphDatabaseService db = dbRule.getGraphDatabaseService(); ChangedLabels labels = (ChangedLabels) db.registerTransactionEventHandler(new ChangedLabels()); try { // when try (Transaction tx = db.beginTx()) { Node node1 = db.createNode(), node2 = db.createNode(), node3 = db.createNode(); labels.add(node1, "Foo"); labels.add(node2, "Bar"); labels.add(node3, "Baz"); labels.add(node3, "Bar"); labels.activate(); tx.success(); } // then assertTrue(labels.isEmpty()); } finally { db.unregisterTransactionEventHandler(labels); } }
@Test public void testRegisterUnregisterHandlers() { Object value1 = 10; Object value2 = 3.5D; DummyTransactionEventHandler<Integer> handler1 = new DummyTransactionEventHandler<>((Integer) value1); DummyTransactionEventHandler<Double> handler2 = new DummyTransactionEventHandler<>((Double) value2); GraphDatabaseService db = dbRule.getGraphDatabaseService(); try { db.unregisterTransactionEventHandler(handler1); fail("Shouldn't be able to do unregister on a unregistered handler"); } catch (IllegalStateException e) { /* Good */ } assertTrue(handler1 == db.registerTransactionEventHandler(handler1)); assertTrue(handler1 == db.registerTransactionEventHandler(handler1)); assertTrue(handler1 == db.unregisterTransactionEventHandler(handler1)); try { db.unregisterTransactionEventHandler(handler1); fail("Shouldn't be able to do unregister on a unregistered handler"); } catch (IllegalStateException e) { /* Good */ } assertTrue(handler1 == db.registerTransactionEventHandler(handler1)); assertTrue(handler2 == db.registerTransactionEventHandler(handler2)); assertTrue(handler1 == db.unregisterTransactionEventHandler(handler1)); assertTrue(handler2 == db.unregisterTransactionEventHandler(handler2)); db.registerTransactionEventHandler(handler1); try (Transaction tx = db.beginTx()) { db.createNode().delete(); tx.success(); } assertNotNull(handler1.beforeCommit); assertNotNull(handler1.afterCommit); assertNull(handler1.afterRollback); assertEquals(value1, handler1.receivedState); assertNotNull(handler1.receivedTransactionData); db.unregisterTransactionEventHandler(handler1); }
@Test public void makeSureBeforeAfterAreCalledCorrectly() { List<TransactionEventHandler<Object>> handlers = new ArrayList<>(); handlers.add(new FailingEventHandler<>(new DummyTransactionEventHandler<>(null), false)); handlers.add(new FailingEventHandler<>(new DummyTransactionEventHandler<>(null), false)); handlers.add(new FailingEventHandler<>(new DummyTransactionEventHandler<>(null), true)); handlers.add(new FailingEventHandler<>(new DummyTransactionEventHandler<>(null), false)); GraphDatabaseService db = dbRule.getGraphDatabaseService(); for (TransactionEventHandler<Object> handler : handlers) { db.registerTransactionEventHandler(handler); } try { Transaction tx = db.beginTx(); try { db.createNode().delete(); tx.success(); tx.close(); fail("Should fail commit"); } catch (TransactionFailureException e) { // OK } verifyHandlerCalls(handlers, false); db.unregisterTransactionEventHandler(handlers.remove(2)); for (TransactionEventHandler<Object> handler : handlers) { ((DummyTransactionEventHandler<Object>) ((FailingEventHandler<Object>) handler).source) .reset(); } try (Transaction transaction = db.beginTx()) { db.createNode().delete(); transaction.success(); } verifyHandlerCalls(handlers, true); } finally { for (TransactionEventHandler<Object> handler : handlers) { db.unregisterTransactionEventHandler(handler); } } }
@Test public void makeSureHandlerIsntCalledWhenTxRolledBack() { DummyTransactionEventHandler<Integer> handler = new DummyTransactionEventHandler<Integer>(10); GraphDatabaseService db = dbRule.getGraphDatabaseService(); db.registerTransactionEventHandler(handler); try { try (Transaction tx = db.beginTx()) { db.createNode().delete(); } assertNull(handler.beforeCommit); assertNull(handler.afterCommit); assertNull(handler.afterRollback); } finally { db.unregisterTransactionEventHandler(handler); } }
@Test public void makeSureHandlersCantBeRegisteredTwice() { DummyTransactionEventHandler<Object> handler = new DummyTransactionEventHandler<>(null); GraphDatabaseService db = dbRule.getGraphDatabaseService(); db.registerTransactionEventHandler(handler); db.registerTransactionEventHandler(handler); try (Transaction tx = db.beginTx()) { db.createNode().delete(); tx.success(); } assertEquals(Integer.valueOf(0), handler.beforeCommit); assertEquals(Integer.valueOf(1), handler.afterCommit); assertNull(handler.afterRollback); db.unregisterTransactionEventHandler(handler); }
@Test public void modifiedPropertyCanByFurtherModifiedInBeforeCommit() throws Exception { // Given // -- create node and set property on it in one transaction GraphDatabaseService db = dbRule.getGraphDatabaseService(); final String key = "key"; final Object value1 = "the old value"; final Object value2 = "the new value"; final Node node; try (Transaction tx = db.beginTx()) { node = db.createNode(); node.setProperty(key, "initial value"); tx.success(); } // -- register a tx handler which will override a property TransactionEventHandler<Void> handler = new TransactionEventHandler.Adapter<Void>() { @Override public Void beforeCommit(TransactionData data) throws Exception { Node modifiedNode = data.assignedNodeProperties().iterator().next().entity(); assertEquals(node, modifiedNode); modifiedNode.setProperty(key, value2); return null; } }; db.registerTransactionEventHandler(handler); try (Transaction tx = db.beginTx()) { // When node.setProperty(key, value1); tx.success(); } // Then assertThat(node, inTx(db, hasProperty(key).withValue(value2))); db.unregisterTransactionEventHandler(handler); }
@Test public void shouldGetCorrectTransactionDataUponCommit() { // Create new data, nothing modified, just added/created ExpectedTransactionData expectedData = new ExpectedTransactionData(); VerifyingTransactionEventHandler handler = new VerifyingTransactionEventHandler(expectedData); GraphDatabaseService db = dbRule.getGraphDatabaseService(); db.registerTransactionEventHandler(handler); Node node1 = null, node2, node3 = null; Relationship rel1 = null, rel2 = null; try { try (Transaction tx = db.beginTx()) { node1 = db.createNode(); expectedData.expectedCreatedNodes.add(node1); node2 = db.createNode(); expectedData.expectedCreatedNodes.add(node2); rel1 = node1.createRelationshipTo(node2, RelTypes.TXEVENT); expectedData.expectedCreatedRelationships.add(rel1); node1.setProperty("name", "Mattias"); expectedData.assignedProperty(node1, "name", "Mattias", null); node1.setProperty("last name", "Persson"); expectedData.assignedProperty(node1, "last name", "Persson", null); node1.setProperty("counter", 10); expectedData.assignedProperty(node1, "counter", 10, null); rel1.setProperty("description", "A description"); expectedData.assignedProperty(rel1, "description", "A description", null); rel1.setProperty("number", 4.5D); expectedData.assignedProperty(rel1, "number", 4.5D, null); node3 = db.createNode(); expectedData.expectedCreatedNodes.add(node3); rel2 = node3.createRelationshipTo(node2, RelTypes.TXEVENT); expectedData.expectedCreatedRelationships.add(rel2); node3.setProperty("name", "Node 3"); expectedData.assignedProperty(node3, "name", "Node 3", null); tx.success(); } assertTrue("Should have been invoked", handler.hasBeenCalled()); if (handler.failure() != null) { throw new RuntimeException(handler.failure()); } } finally { db.unregisterTransactionEventHandler(handler); } // Use the above data and modify it, change properties, delete stuff expectedData = new ExpectedTransactionData(); handler = new VerifyingTransactionEventHandler(expectedData); db.registerTransactionEventHandler(handler); try { try (Transaction tx = db.beginTx()) { Node newNode = db.createNode(); expectedData.expectedCreatedNodes.add(newNode); Node tempNode = db.createNode(); Relationship tempRel = tempNode.createRelationshipTo(node1, RelTypes.TXEVENT); tempNode.setProperty("something", "Some value"); tempRel.setProperty("someproperty", 101010); tempNode.removeProperty("nothing"); node3.setProperty("test", "hello"); node3.setProperty("name", "No name"); node3.delete(); expectedData.expectedDeletedNodes.add(node3); expectedData.removedProperty(node3, "name", null, "Node 3"); node1.setProperty("new name", "A name"); node1.setProperty("new name", "A better name"); expectedData.assignedProperty(node1, "new name", "A better name", null); node1.setProperty("name", "Nothing"); node1.setProperty("name", "Mattias Persson"); expectedData.assignedProperty(node1, "name", "Mattias Persson", "Mattias"); node1.removeProperty("counter"); expectedData.removedProperty(node1, "counter", null, 10); node1.removeProperty("last name"); node1.setProperty("last name", "Hi"); expectedData.assignedProperty(node1, "last name", "Hi", "Persson"); rel2.delete(); expectedData.expectedDeletedRelationships.add(rel2); rel1.removeProperty("number"); expectedData.removedProperty(rel1, "number", null, 4.5D); rel1.setProperty("description", "Ignored"); rel1.setProperty("description", "New"); expectedData.assignedProperty(rel1, "description", "New", "A description"); tempRel.delete(); tempNode.delete(); tx.success(); } assertTrue("Should have been invoked", handler.hasBeenCalled()); if (handler.failure() != null) { throw new RuntimeException(handler.failure()); } } finally { db.unregisterTransactionEventHandler(handler); } }
@Test public void shouldAccessRelationshipDataInAfterCommit() throws Exception { // GIVEN final GraphDatabaseService db = dbRule.getGraphDatabaseService(); final AtomicInteger accessCount = new AtomicInteger(); final Map<Long, Triplet<Node, String, Node>> expectedRelationshipData = new HashMap<>(); TransactionEventHandler<Void> handler = new TransactionEventHandler.Adapter<Void>() { @Override public void afterCommit(TransactionData data, Void state) { accessCount.set(0); try (Transaction tx = db.beginTx()) { for (Relationship relationship : data.createdRelationships()) { accessData(relationship); } for (PropertyEntry<Relationship> change : data.assignedRelationshipProperties()) { accessData(change.entity()); } for (PropertyEntry<Relationship> change : data.removedRelationshipProperties()) { accessData(change.entity()); } tx.success(); } } private void accessData(Relationship relationship) { accessCount.incrementAndGet(); Triplet<Node, String, Node> expectancy = expectedRelationshipData.get(relationship.getId()); assertNotNull(expectancy); assertEquals(expectancy.first(), relationship.getStartNode()); assertEquals(expectancy.second(), relationship.getType().name()); assertEquals(expectancy.third(), relationship.getEndNode()); } }; db.registerTransactionEventHandler(handler); // WHEN try { Relationship relationship; try (Transaction tx = db.beginTx()) { relationship = db.createNode().createRelationshipTo(db.createNode(), MyRelTypes.TEST); expectedRelationshipData.put( relationship.getId(), Triplet.of( relationship.getStartNode(), relationship.getType().name(), relationship.getEndNode())); tx.success(); } // THEN assertEquals(1, accessCount.get()); // and WHEN try (Transaction tx = db.beginTx()) { relationship.setProperty("name", "Smith"); Relationship otherRelationship = db.createNode().createRelationshipTo(db.createNode(), MyRelTypes.TEST2); expectedRelationshipData.put( otherRelationship.getId(), Triplet.of( otherRelationship.getStartNode(), otherRelationship.getType().name(), otherRelationship.getEndNode())); tx.success(); } // THEN assertEquals(2, accessCount.get()); // and WHEN try (Transaction tx = db.beginTx()) { relationship.delete(); tx.success(); } // THEN assertEquals(1, accessCount.get()); } finally { db.unregisterTransactionEventHandler(handler); } }