diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
index d38dc08d686a20c2428404d5593302e675be95dc..5592042b12992ccb4cf6aed23a18a4c931f8e225 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
+++ b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
@@ -49,9 +49,9 @@ public interface DatabaseComponent {
 	Transaction startTransaction() throws DbException;
 
 	/**
-	 * Ends a transaction. If the transaction's
-	 * {@link Transaction#setComplete() commit} flag is set, the
-	 * transaction is committed, otherwise it is aborted.
+	 * Ends a transaction. If the transaction is marked as complete, the
+	 * transaction is committed and any events attached to the transaction are
+	 * broadcast; otherwise the transaction is aborted.
 	 */
 	void endTransaction(Transaction txn) throws DbException;
 
diff --git a/briar-api/src/org/briarproject/api/db/Transaction.java b/briar-api/src/org/briarproject/api/db/Transaction.java
index 46497a039e8dc8c43a99ca2e11165377030b871b..cb89f142ca3461582180f53f9ffb9e557e0cdc64 100644
--- a/briar-api/src/org/briarproject/api/db/Transaction.java
+++ b/briar-api/src/org/briarproject/api/db/Transaction.java
@@ -1,11 +1,19 @@
 package org.briarproject.api.db;
 
+import org.briarproject.api.event.Event;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * A wrapper around a database transaction. Transactions are not thread-safe.
  */
 public class Transaction {
 
 	private final Object txn;
+
+	private List<Event> events = null;
 	private boolean complete = false;
 
 	public Transaction(Object txn) {
@@ -20,6 +28,23 @@ public class Transaction {
 		return txn;
 	}
 
+	/**
+	 * Attaches an event to be broadcast when the transaction has been
+	 * committed.
+	 */
+	public void attach(Event e) {
+		if (events == null) events = new ArrayList<Event>();
+		events.add(e);
+	}
+
+	/**
+	 * Returns any events attached to the transaction.
+	 */
+	public List<Event> getEvents() {
+		if (events == null) return Collections.emptyList();
+		return events;
+	}
+
 	/**
 	 * Returns true if the transaction is ready to be committed.
 	 */
diff --git a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java b/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
index 7bdb3bc450357afc1f5b5c215e902a523ac76829..4edc0654584013b2350c7b85f6c44690d06b6438 100644
--- a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
+++ b/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
@@ -9,9 +9,6 @@ import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.NoSuchContactException;
 import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.ContactAddedEvent;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.EventBus;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.identity.IdentityManager.RemoveIdentityHook;
@@ -37,14 +34,12 @@ class ContactManagerImpl implements ContactManager, Service,
 			Logger.getLogger(ContactManagerImpl.class.getName());
 
 	private final DatabaseComponent db;
-	private final EventBus eventBus;
 	private final List<AddContactHook> addHooks;
 	private final List<RemoveContactHook> removeHooks;
 
 	@Inject
-	ContactManagerImpl(DatabaseComponent db, EventBus eventBus) {
+	ContactManagerImpl(DatabaseComponent db) {
 		this.db = db;
-		this.eventBus = eventBus;
 		addHooks = new CopyOnWriteArrayList<AddContactHook>();
 		removeHooks = new CopyOnWriteArrayList<RemoveContactHook>();
 	}
@@ -53,8 +48,6 @@ class ContactManagerImpl implements ContactManager, Service,
 	public boolean start() {
 		// Finish adding/removing any partly added/removed contacts
 		try {
-			List<ContactId> added = new ArrayList<ContactId>();
-			List<ContactId> removed = new ArrayList<ContactId>();
 			Transaction txn = db.startTransaction();
 			try {
 				for (Contact c : db.getContacts(txn)) {
@@ -62,22 +55,16 @@ class ContactManagerImpl implements ContactManager, Service,
 						for (AddContactHook hook : addHooks)
 							hook.addingContact(txn, c);
 						db.setContactStatus(txn, c.getId(), ACTIVE);
-						added.add(c.getId());
 					} else if (c.getStatus().equals(REMOVING)) {
 						for (RemoveContactHook hook : removeHooks)
 							hook.removingContact(txn, c);
 						db.removeContact(txn, c.getId());
-						removed.add(c.getId());
 					}
 				}
 				txn.setComplete();
 			} finally {
 				db.endTransaction(txn);
 			}
-			for (ContactId c : added)
-				eventBus.broadcast(new ContactAddedEvent(c));
-			for (ContactId c : removed)
-				eventBus.broadcast(new ContactRemovedEvent(c));
 			return true;
 		} catch (DbException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
@@ -115,7 +102,6 @@ class ContactManagerImpl implements ContactManager, Service,
 		} finally {
 			db.endTransaction(txn);
 		}
-		eventBus.broadcast(new ContactAddedEvent(c));
 		return c;
 	}
 
@@ -159,7 +145,6 @@ class ContactManagerImpl implements ContactManager, Service,
 		} finally {
 			db.endTransaction(txn);
 		}
-		eventBus.broadcast(new ContactRemovedEvent(c));
 	}
 
 	private void removeContact(Transaction txn, ContactId c)
diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
index 8d4c71166571957f33fb02f291dedf4ca47318f1..00e064883cf0a5fb7ebf6e4597ccbb53c53d8b29 100644
--- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
+++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
@@ -15,10 +15,15 @@ import org.briarproject.api.db.NoSuchMessageException;
 import org.briarproject.api.db.NoSuchTransportException;
 import org.briarproject.api.db.StorageStatus;
 import org.briarproject.api.db.Transaction;
+import org.briarproject.api.event.ContactAddedEvent;
+import org.briarproject.api.event.ContactRemovedEvent;
+import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.GroupAddedEvent;
 import org.briarproject.api.event.GroupRemovedEvent;
 import org.briarproject.api.event.GroupVisibilityUpdatedEvent;
+import org.briarproject.api.event.LocalAuthorAddedEvent;
+import org.briarproject.api.event.LocalAuthorRemovedEvent;
 import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.event.MessageRequestedEvent;
 import org.briarproject.api.event.MessageSharedEvent;
@@ -66,8 +71,6 @@ import static org.briarproject.api.sync.ValidationManager.Validity.UNKNOWN;
 import static org.briarproject.api.sync.ValidationManager.Validity.VALID;
 import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
 
-// TODO: Callers should broadcast events after committing transactions
-
 /**
  * An implementation of DatabaseComponent using reentrant read-write locks.
  * Depending on the JVM's lock implementation, this implementation may allow
@@ -127,8 +130,12 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 
 	public void endTransaction(Transaction transaction) throws DbException {
 		T txn = txnClass.cast(transaction.unbox());
-		if (transaction.isComplete()) db.commitTransaction(txn);
-		else db.abortTransaction(txn);
+		if (transaction.isComplete()) {
+			db.commitTransaction(txn);
+			for (Event e : transaction.getEvents()) eventBus.broadcast(e);
+		} else {
+			db.abortTransaction(txn);
+		}
 	}
 
 	private T unbox(Transaction transaction) {
@@ -143,42 +150,40 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 			throw new NoSuchLocalAuthorException();
 		if (db.containsContact(txn, remote.getId(), local))
 			throw new ContactExistsException();
-		return db.addContact(txn, remote, local);
+		ContactId c = db.addContact(txn, remote, local);
+		transaction.attach(new ContactAddedEvent(c));
+		return c;
 	}
 
 	public void addGroup(Transaction transaction, Group g) throws DbException {
-		boolean added = false;
 		T txn = unbox(transaction);
 		if (!db.containsGroup(txn, g.getId())) {
 			db.addGroup(txn, g);
-			added = true;
+			transaction.attach(new GroupAddedEvent(g));
 		}
-		if (added) eventBus.broadcast(new GroupAddedEvent(g));
 	}
 
 	public void addLocalAuthor(Transaction transaction, LocalAuthor a)
 			throws DbException {
 		T txn = unbox(transaction);
-		if (!db.containsLocalAuthor(txn, a.getId()))
+		if (!db.containsLocalAuthor(txn, a.getId())) {
 			db.addLocalAuthor(txn, a);
+			transaction.attach(new LocalAuthorAddedEvent(a.getId()));
+		}
 	}
 
 	public void addLocalMessage(Transaction transaction, Message m, ClientId c,
 			Metadata meta, boolean shared) throws DbException {
-		boolean added = false;
 		T txn = unbox(transaction);
 		if (!db.containsGroup(txn, m.getGroupId()))
 			throw new NoSuchGroupException();
 		if (!db.containsMessage(txn, m.getId())) {
 			addMessage(txn, m, VALID, shared, null);
-			added = true;
+			transaction.attach(new MessageAddedEvent(m, null));
+			transaction.attach(new MessageValidatedEvent(m, c, true, true));
+			if (shared) transaction.attach(new MessageSharedEvent(m));
 		}
 		db.mergeMessageMetadata(txn, m.getId(), meta);
-		if (added) {
-			eventBus.broadcast(new MessageAddedEvent(m, null));
-			eventBus.broadcast(new MessageValidatedEvent(m, c, true, true));
-			if (shared) eventBus.broadcast(new MessageSharedEvent(m));
-		}
 	}
 
 	/**
@@ -206,13 +211,11 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 
 	public void addTransport(Transaction transaction, TransportId t,
 			int maxLatency) throws DbException {
-		boolean added = false;
 		T txn = unbox(transaction);
 		if (!db.containsTransport(txn, t)) {
 			db.addTransport(txn, t, maxLatency);
-			added = true;
+			transaction.attach(new TransportAddedEvent(t, maxLatency));
 		}
-		if (added) eventBus.broadcast(new TransportAddedEvent(t, maxLatency));
 	}
 
 	public void addTransportKeys(Transaction transaction, ContactId c,
@@ -266,9 +269,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 			messages.add(db.getRawMessage(txn, m));
 			db.updateExpiryTime(txn, c, m, maxLatency);
 		}
-		if (!ids.isEmpty()) db.lowerRequestedFlag(txn, c, ids);
-		if (messages.isEmpty()) return null;
-		if (!ids.isEmpty()) eventBus.broadcast(new MessagesSentEvent(c, ids));
+		if (ids.isEmpty()) return null;
+		db.lowerRequestedFlag(txn, c, ids);
+		transaction.attach(new MessagesSentEvent(c, ids));
 		return Collections.unmodifiableList(messages);
 	}
 
@@ -309,9 +312,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 			messages.add(db.getRawMessage(txn, m));
 			db.updateExpiryTime(txn, c, m, maxLatency);
 		}
-		if (!ids.isEmpty()) db.lowerRequestedFlag(txn, c, ids);
-		if (messages.isEmpty()) return null;
-		if (!ids.isEmpty()) eventBus.broadcast(new MessagesSentEvent(c, ids));
+		if (ids.isEmpty()) return null;
+		db.lowerRequestedFlag(txn, c, ids);
+		transaction.attach(new MessagesSentEvent(c, ids));
 		return Collections.unmodifiableList(messages);
 	}
 
@@ -486,7 +489,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 
 	public void mergeSettings(Transaction transaction, Settings s,
 			String namespace) throws DbException {
-		boolean changed = false;
 		T txn = unbox(transaction);
 		Settings old = db.getSettings(txn, namespace);
 		Settings merged = new Settings();
@@ -494,9 +496,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		merged.putAll(s);
 		if (!merged.equals(old)) {
 			db.mergeSettings(txn, s, namespace);
-			changed = true;
+			transaction.attach(new SettingsUpdatedEvent(namespace));
 		}
-		if (changed) eventBus.broadcast(new SettingsUpdatedEvent(namespace));
 	}
 
 	public void receiveAck(Transaction transaction, ContactId c, Ack a)
@@ -511,24 +512,21 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 				acked.add(m);
 			}
 		}
-		eventBus.broadcast(new MessagesAckedEvent(c, acked));
+		transaction.attach(new MessagesAckedEvent(c, acked));
 	}
 
 	public void receiveMessage(Transaction transaction, ContactId c, Message m)
 			throws DbException {
-		boolean duplicate, visible;
 		T txn = unbox(transaction);
 		if (!db.containsContact(txn, c))
 			throw new NoSuchContactException();
-		duplicate = db.containsMessage(txn, m.getId());
-		visible = db.containsVisibleGroup(txn, c, m.getGroupId());
-		if (visible) {
-			if (!duplicate) addMessage(txn, m, UNKNOWN, false, c);
+		if (db.containsVisibleGroup(txn, c, m.getGroupId())) {
+			if (!db.containsMessage(txn, m.getId())) {
+				addMessage(txn, m, UNKNOWN, false, c);
+				transaction.attach(new MessageAddedEvent(m, c));
+			}
 			db.raiseAckFlag(txn, c, m.getId());
-		}
-		if (visible) {
-			if (!duplicate) eventBus.broadcast(new MessageAddedEvent(m, c));
-			eventBus.broadcast(new MessageToAckEvent(c));
+			transaction.attach(new MessageToAckEvent(c));
 		}
 	}
 
@@ -550,8 +548,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 				count++;
 			}
 		}
-		if (ack) eventBus.broadcast(new MessageToAckEvent(c));
-		if (request) eventBus.broadcast(new MessageToRequestEvent(c));
+		if (ack) transaction.attach(new MessageToAckEvent(c));
+		if (request) transaction.attach(new MessageToRequestEvent(c));
 	}
 
 	public void receiveRequest(Transaction transaction, ContactId c, Request r)
@@ -567,7 +565,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 				requested = true;
 			}
 		}
-		if (requested) eventBus.broadcast(new MessageRequestedEvent(c));
+		if (requested) transaction.attach(new MessageRequestedEvent(c));
 	}
 
 	public void removeContact(Transaction transaction, ContactId c)
@@ -576,6 +574,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		if (!db.containsContact(txn, c))
 			throw new NoSuchContactException();
 		db.removeContact(txn, c);
+		transaction.attach(new ContactRemovedEvent(c));
 	}
 
 	public void removeGroup(Transaction transaction, Group g)
@@ -587,8 +586,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 			throw new NoSuchGroupException();
 		affected = db.getVisibility(txn, id);
 		db.removeGroup(txn, id);
-		eventBus.broadcast(new GroupRemovedEvent(g));
-		eventBus.broadcast(new GroupVisibilityUpdatedEvent(affected));
+		transaction.attach(new GroupRemovedEvent(g));
+		transaction.attach(new GroupVisibilityUpdatedEvent(affected));
 	}
 
 	public void removeLocalAuthor(Transaction transaction, AuthorId a)
@@ -597,6 +596,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		if (!db.containsLocalAuthor(txn, a))
 			throw new NoSuchLocalAuthorException();
 		db.removeLocalAuthor(txn, a);
+		transaction.attach(new LocalAuthorRemovedEvent(a));
 	}
 
 	public void removeTransport(Transaction transaction, TransportId t)
@@ -605,7 +605,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		if (!db.containsTransport(txn, t))
 			throw new NoSuchTransportException();
 		db.removeTransport(txn, t);
-		eventBus.broadcast(new TransportRemovedEvent(t));
+		transaction.attach(new TransportRemovedEvent(t));
 	}
 
 	public void setContactStatus(Transaction transaction, ContactId c,
@@ -630,7 +630,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		if (!db.containsMessage(txn, m.getId()))
 			throw new NoSuchMessageException();
 		db.setMessageShared(txn, m.getId(), shared);
-		if (shared) eventBus.broadcast(new MessageSharedEvent(m));
+		if (shared) transaction.attach(new MessageSharedEvent(m));
 	}
 
 	public void setMessageValid(Transaction transaction, Message m, ClientId c,
@@ -639,7 +639,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		if (!db.containsMessage(txn, m.getId()))
 			throw new NoSuchMessageException();
 		db.setMessageValid(txn, m.getId(), valid);
-		eventBus.broadcast(new MessageValidatedEvent(m, c, false, valid));
+		transaction.attach(new MessageValidatedEvent(m, c, false, valid));
 	}
 
 	public void setReorderingWindow(Transaction transaction, ContactId c,
@@ -665,8 +665,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		if (visible && !wasVisible) db.addVisibility(txn, c, g);
 		else if (!visible && wasVisible) db.removeVisibility(txn, c, g);
 		if (visible != wasVisible) {
-			eventBus.broadcast(new GroupVisibilityUpdatedEvent(
-					Collections.singletonList(c)));
+			List<ContactId> affected = Collections.singletonList(c);
+			transaction.attach(new GroupVisibilityUpdatedEvent(affected));
 		}
 	}
 
diff --git a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java b/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
index 475ead3e4a1321e7906a115b38a09c68f24e3319..93997dbb3d9a9128b53303ad6c3a4dd7d0c434c3 100644
--- a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
+++ b/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
@@ -6,9 +6,6 @@ import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.NoSuchLocalAuthorException;
 import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.LocalAuthorAddedEvent;
-import org.briarproject.api.event.LocalAuthorRemovedEvent;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
@@ -32,14 +29,12 @@ class IdentityManagerImpl implements IdentityManager, Service {
 			Logger.getLogger(IdentityManagerImpl.class.getName());
 
 	private final DatabaseComponent db;
-	private final EventBus eventBus;
 	private final List<AddIdentityHook> addHooks;
 	private final List<RemoveIdentityHook> removeHooks;
 
 	@Inject
-	IdentityManagerImpl(DatabaseComponent db, EventBus eventBus) {
+	IdentityManagerImpl(DatabaseComponent db) {
 		this.db = db;
-		this.eventBus = eventBus;
 		addHooks = new CopyOnWriteArrayList<AddIdentityHook>();
 		removeHooks = new CopyOnWriteArrayList<RemoveIdentityHook>();
 	}
@@ -48,8 +43,6 @@ class IdentityManagerImpl implements IdentityManager, Service {
 	public boolean start() {
 		// Finish adding/removing any partly added/removed pseudonyms
 		try {
-			List<AuthorId> added = new ArrayList<AuthorId>();
-			List<AuthorId> removed = new ArrayList<AuthorId>();
 			Transaction txn = db.startTransaction();
 			try {
 				for (LocalAuthor a : db.getLocalAuthors(txn)) {
@@ -57,22 +50,16 @@ class IdentityManagerImpl implements IdentityManager, Service {
 						for (AddIdentityHook hook : addHooks)
 							hook.addingIdentity(txn, a);
 						db.setLocalAuthorStatus(txn, a.getId(), ACTIVE);
-						added.add(a.getId());
 					} else if (a.getStatus().equals(REMOVING)) {
 						for (RemoveIdentityHook hook : removeHooks)
 							hook.removingIdentity(txn, a);
 						db.removeLocalAuthor(txn, a.getId());
-						removed.add(a.getId());
 					}
 				}
 				txn.setComplete();
 			} finally {
 				db.endTransaction(txn);
 			}
-			for (AuthorId a : added)
-				eventBus.broadcast(new LocalAuthorAddedEvent(a));
-			for (AuthorId a : removed)
-				eventBus.broadcast(new LocalAuthorRemovedEvent(a));
 			return true;
 		} catch (DbException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
@@ -107,7 +94,6 @@ class IdentityManagerImpl implements IdentityManager, Service {
 		} finally {
 			db.endTransaction(txn);
 		}
-		eventBus.broadcast(new LocalAuthorAddedEvent(localAuthor.getId()));
 	}
 
 	@Override
@@ -154,6 +140,5 @@ class IdentityManagerImpl implements IdentityManager, Service {
 		} finally {
 			db.endTransaction(txn);
 		}
-		eventBus.broadcast(new LocalAuthorRemovedEvent(a));
 	}
 }
diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
index 48e6ea037b05ad57cf77e2a91952323e5f4d0385..a56542d38f28f542cf90237815945e34b4986576 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
+++ b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
@@ -15,10 +15,14 @@ import org.briarproject.api.db.NoSuchMessageException;
 import org.briarproject.api.db.NoSuchTransportException;
 import org.briarproject.api.db.StorageStatus;
 import org.briarproject.api.db.Transaction;
+import org.briarproject.api.event.ContactAddedEvent;
+import org.briarproject.api.event.ContactRemovedEvent;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.GroupAddedEvent;
 import org.briarproject.api.event.GroupRemovedEvent;
 import org.briarproject.api.event.GroupVisibilityUpdatedEvent;
+import org.briarproject.api.event.LocalAuthorAddedEvent;
+import org.briarproject.api.event.LocalAuthorRemovedEvent;
 import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.event.MessageRequestedEvent;
 import org.briarproject.api.event.MessageSharedEvent;
@@ -136,6 +140,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			oneOf(database).containsLocalAuthor(txn, localAuthorId);
 			will(returnValue(false));
 			oneOf(database).addLocalAuthor(txn, localAuthor);
+			oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
 			// addContact()
 			oneOf(database).containsLocalAuthor(txn, localAuthorId);
 			will(returnValue(true));
@@ -143,6 +148,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			will(returnValue(false));
 			oneOf(database).addContact(txn, author, localAuthorId);
 			will(returnValue(contactId));
+			oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
 			// getContacts()
 			oneOf(database).getContacts(txn);
 			will(returnValue(Collections.singletonList(contact)));
@@ -170,10 +176,12 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			oneOf(database).containsContact(txn, contactId);
 			will(returnValue(true));
 			oneOf(database).removeContact(txn, contactId);
+			oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class)));
 			// removeLocalAuthor()
 			oneOf(database).containsLocalAuthor(txn, localAuthorId);
 			will(returnValue(true));
 			oneOf(database).removeLocalAuthor(txn, localAuthorId);
+			oneOf(eventBus).broadcast(with(any(LocalAuthorRemovedEvent.class)));
 			// endTransaction()
 			oneOf(database).commitTransaction(txn);
 			// close()
@@ -743,6 +751,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			oneOf(database).containsLocalAuthor(txn, localAuthorId);
 			will(returnValue(false));
 			oneOf(database).addLocalAuthor(txn, localAuthor);
+			oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
 			// addContact()
 			oneOf(database).containsLocalAuthor(txn, localAuthorId);
 			will(returnValue(true));
@@ -750,6 +759,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			will(returnValue(false));
 			oneOf(database).addContact(txn, author, localAuthorId);
 			will(returnValue(contactId));
+			oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
 			// endTransaction()
 			oneOf(database).commitTransaction(txn);
 			// Check whether the transport is in the DB (which it's not)
@@ -1137,8 +1147,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			will(returnValue(txn));
 			oneOf(database).containsContact(txn, contactId);
 			will(returnValue(true));
-			oneOf(database).containsMessage(txn, messageId);
-			will(returnValue(false));
 			oneOf(database).containsVisibleGroup(txn, contactId, groupId);
 			will(returnValue(false));
 			oneOf(database).commitTransaction(txn);