diff --git a/briar-android/src/org/briarproject/android/blogs/BaseController.java b/briar-android/src/org/briarproject/android/blogs/BaseController.java
index a2f4b7d26a852a908dd715df91bf808227e726de..9e94d668de1d3b2fdb8fec4d4ab804552e648f9f 100644
--- a/briar-android/src/org/briarproject/android/blogs/BaseController.java
+++ b/briar-android/src/org/briarproject/android/blogs/BaseController.java
@@ -4,6 +4,7 @@ import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 
 import org.briarproject.android.DestroyableContext;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.blogs.BlogPostHeader;
 import org.briarproject.api.db.DbException;
@@ -30,7 +31,7 @@ interface BaseController {
 			ResultExceptionHandler<BlogPostItem, DbException> handler);
 
 	void repeatPost(BlogPostItem item, @Nullable String comment,
-			ResultExceptionHandler<Void, DbException> resultHandler);
+			ExceptionHandler<DbException> handler);
 
 	void setOnBlogPostAddedListener(OnBlogPostAddedListener listener);
 
diff --git a/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java b/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java
index 7ff91c18bde74948718295728c12630f3b1483e4..ec563fbf37e7572e89183932687fd2ed53e87d04 100644
--- a/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java
@@ -5,6 +5,7 @@ import android.support.annotation.Nullable;
 
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.controller.DbControllerImpl;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.blogs.Blog;
 import org.briarproject.api.blogs.BlogCommentHeader;
@@ -196,7 +197,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
 	@Override
 	public void repeatPost(final BlogPostItem item,
 			final @Nullable String comment,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
@@ -205,7 +206,6 @@ abstract class BaseControllerImpl extends DbControllerImpl
 					Blog b = blogManager.getPersonalBlog(a);
 					BlogPostHeader h = item.getHeader();
 					blogManager.addLocalComment(a, b.getId(), comment, h);
-					handler.onResult(null);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java b/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
index 35b57773e69fd9609e9f4b4ddb6e3041f3c94f7b..fb5f43edc7b91c85eedefa7297fb733623129b58 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
+++ b/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
@@ -23,12 +23,14 @@ import org.briarproject.android.blogs.BaseController.OnBlogPostAddedListener;
 import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.sharing.ShareBlogActivity;
 import org.briarproject.android.sharing.BlogSharingStatusActivity;
+import org.briarproject.android.sharing.ShareBlogActivity;
 import org.briarproject.android.view.BriarRecyclerView;
 import org.briarproject.api.blogs.BlogPostHeader;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.identity.Author;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.api.sync.GroupId;
 
 import java.util.Collection;
@@ -44,6 +46,8 @@ import static org.briarproject.android.BriarActivity.GROUP_ID;
 import static org.briarproject.android.blogs.BlogActivity.REQUEST_SHARE;
 import static org.briarproject.android.blogs.BlogActivity.REQUEST_WRITE_POST;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class BlogFragment extends BaseFragment implements
 		OnBlogPostAddedListener {
 
@@ -71,8 +75,9 @@ public class BlogFragment extends BaseFragment implements
 
 	@Nullable
 	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 		Bundle args = getArguments();
 		byte[] b = args.getByteArray(GROUP_ID);
 		if (b == null) throw new IllegalStateException("No group ID in args");
diff --git a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java b/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
index a69e9ce96bea51d6b5c1e2693f50ae8606730cb1..3f83f380feafc063506f99e3ed40b5f018a0088e 100644
--- a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
+++ b/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
@@ -1,6 +1,5 @@
 package org.briarproject.android.blogs;
 
-import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.view.LayoutInflater;
@@ -11,11 +10,14 @@ import android.widget.ScrollView;
 
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
+import org.briarproject.android.controller.handler.UiExceptionHandler;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.fragment.BaseFragment;
 import org.briarproject.android.view.TextInputView;
 import org.briarproject.android.view.TextInputView.TextInputListener;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
 
@@ -28,11 +30,12 @@ import static android.view.View.VISIBLE;
 import static org.briarproject.android.BriarActivity.GROUP_ID;
 import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class ReblogFragment extends BaseFragment implements TextInputListener {
 
 	public static final String TAG = ReblogFragment.class.getName();
 
-	private BaseFragmentListener listener;
 	private ViewHolder ui;
 	private GroupId blogId;
 	private MessageId postId;
@@ -63,14 +66,9 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
 	}
 
 	@Override
-	public void onAttach(Context context) {
-		super.onAttach(context);
-		listener = (BaseFragmentListener) context;
-	}
-
-	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 
 		Bundle args = getArguments();
 		blogId = new GroupId(args.getByteArray(GROUP_ID));
@@ -130,14 +128,10 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
 	public void onSendClick(String text) {
 		String comment = getComment();
 		feedController.repeatPost(item, comment,
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void result) {
-						// do nothing, this fragment is gone already
-					}
-
+				new UiExceptionHandler<DbException>(this) {
 					@Override
 					public void onExceptionUi(DbException exception) {
+						// TODO proper error handling
 						// do nothing, this fragment is gone already
 					}
 				});
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ExceptionHandler.java b/briar-android/src/org/briarproject/android/controller/handler/ExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d8719a64833f07c26d26e0179d761d80d5d926e
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/handler/ExceptionHandler.java
@@ -0,0 +1,7 @@
+package org.briarproject.android.controller.handler;
+
+public interface ExceptionHandler<E extends Exception> {
+
+	void onException(E exception);
+
+}
diff --git a/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java b/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
index 3743c0804bb8d4646b21a753e930664685087255..b8346a565ff84ab3ad9ef37c38dd731538e6e90a 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
+++ b/briar-android/src/org/briarproject/android/controller/handler/ResultExceptionHandler.java
@@ -1,8 +1,8 @@
 package org.briarproject.android.controller.handler;
 
-public interface ResultExceptionHandler<R, E extends Exception> {
+public interface ResultExceptionHandler<R, E extends Exception>
+		extends ExceptionHandler<E> {
 
 	void onResult(R result);
 
-	void onException(E exception);
 }
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiExceptionHandler.java b/briar-android/src/org/briarproject/android/controller/handler/UiExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..90db65fcd38d71e7897f2bfa43643021adf00777
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/controller/handler/UiExceptionHandler.java
@@ -0,0 +1,34 @@
+package org.briarproject.android.controller.handler;
+
+import android.support.annotation.UiThread;
+
+import org.briarproject.android.DestroyableContext;
+import org.briarproject.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public abstract class UiExceptionHandler<E extends Exception>
+		implements ExceptionHandler<E> {
+
+	protected final DestroyableContext listener;
+
+	protected UiExceptionHandler(DestroyableContext listener) {
+		this.listener = listener;
+	}
+
+	@Override
+	public void onException(final E exception) {
+		listener.runOnUiThreadUnlessDestroyed(new Runnable() {
+			@Override
+			public void run() {
+				onExceptionUi(exception);
+			}
+		});
+	}
+
+	@UiThread
+	public abstract void onExceptionUi(E exception);
+
+}
diff --git a/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java b/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
index b2d01d4f74b997d072cf986ebe14ffc79bdf08a8..8fd4ab4fc9b9ea7d650848f891f6f254c3b48323 100644
--- a/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
+++ b/briar-android/src/org/briarproject/android/controller/handler/UiResultExceptionHandler.java
@@ -3,14 +3,17 @@ package org.briarproject.android.controller.handler;
 import android.support.annotation.UiThread;
 
 import org.briarproject.android.DestroyableContext;
+import org.briarproject.api.nullsafety.NotNullByDefault;
 
-public abstract class UiResultExceptionHandler<R, E extends Exception>
-		implements ResultExceptionHandler<R, E> {
+import javax.annotation.concurrent.Immutable;
 
-	private final DestroyableContext listener;
+@Immutable
+@NotNullByDefault
+public abstract class UiResultExceptionHandler<R, E extends Exception>
+		extends UiExceptionHandler<E> implements ResultExceptionHandler<R, E> {
 
 	protected UiResultExceptionHandler(DestroyableContext listener) {
-		this.listener = listener;
+		super(listener);
 	}
 
 	@Override
@@ -23,19 +26,7 @@ public abstract class UiResultExceptionHandler<R, E extends Exception>
 		});
 	}
 
-	@Override
-	public void onException(final E exception) {
-		listener.runOnUiThreadUnlessDestroyed(new Runnable() {
-			@Override
-			public void run() {
-				onExceptionUi(exception);
-			}
-		});
-	}
-
 	@UiThread
 	public abstract void onResultUi(R result);
 
-	@UiThread
-	public abstract void onExceptionUi(E exception);
 }
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
index 75a194d3246ddbba327f39d0c64d7d1c2dd45b72..24dba86141b70f866ffa67fe9856fa6eadc7b6d8 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
@@ -17,6 +17,7 @@ import android.view.MenuItem;
 
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
+import org.briarproject.android.controller.handler.UiExceptionHandler;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
 import org.briarproject.android.privategroup.creation.GroupInviteActivity;
@@ -24,6 +25,8 @@ import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
 import org.briarproject.android.threaded.ThreadListActivity;
 import org.briarproject.android.threaded.ThreadListController;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.api.privategroup.GroupMessageHeader;
 import org.briarproject.api.privategroup.PrivateGroup;
 
@@ -33,6 +36,8 @@ import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 import static android.view.View.GONE;
 import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class GroupActivity extends
 		ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader>
 		implements GroupListener, OnClickListener {
@@ -247,13 +252,9 @@ public class GroupActivity extends
 	@Override
 	public void onClick(DialogInterface dialog, int which) {
 		controller.deleteNamedGroup(
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void v) {
-						// The activity is going to be destroyed by the
-						// GroupRemovedEvent being fired
-					}
-
+				new UiExceptionHandler<DbException>(this) {
+					// The activity is going to be destroyed by the
+					// GroupRemovedEvent being fired
 					@Override
 					public void onExceptionUi(DbException exception) {
 						// TODO proper error handling
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java b/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
index 791866f2ad2b9377540d66c7e567b5277ba9657f..44573e49aebe8fcf8f4168403500e6617c767e8a 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
+++ b/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
@@ -2,7 +2,6 @@ package org.briarproject.android.privategroup.creation;
 
 import org.briarproject.R;
 import org.briarproject.android.contactselection.ContactSelectorActivity;
-import org.briarproject.android.contactselection.ContactSelectorController;
 import org.briarproject.android.contactselection.SelectableContactItem;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
diff --git a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java
index d77f04c25d8293f1233a296df8ae8ca1267eb7ae..bf4101edc16a93fe5bf097acfb631fc805b0ebc5 100644
--- a/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/invitation/GroupInvitationControllerImpl.java
@@ -1,6 +1,6 @@
 package org.briarproject.android.privategroup.invitation;
 
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.sharing.InvitationControllerImpl;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DatabaseExecutor;
@@ -10,8 +10,8 @@ import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.GroupInvitationRequestReceivedEvent;
 import org.briarproject.api.event.GroupInvitationResponseReceivedEvent;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.nullsafety.NotNullByDefault;
 import org.briarproject.api.privategroup.PrivateGroup;
-import org.briarproject.api.privategroup.PrivateGroupManager;
 import org.briarproject.api.privategroup.invitation.GroupInvitationItem;
 import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
 import org.briarproject.api.sync.ClientId;
@@ -24,20 +24,18 @@ import javax.inject.Inject;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.privategroup.PrivateGroupManager.CLIENT_ID;
 
+@NotNullByDefault
 public class GroupInvitationControllerImpl
 		extends InvitationControllerImpl<GroupInvitationItem>
 		implements GroupInvitationController {
 
-	private final PrivateGroupManager privateGroupManager;
 	private final GroupInvitationManager groupInvitationManager;
 
 	@Inject
 	GroupInvitationControllerImpl(@DatabaseExecutor Executor dbExecutor,
 			LifecycleManager lifecycleManager, EventBus eventBus,
-			PrivateGroupManager privateGroupManager,
 			GroupInvitationManager groupInvitationManager) {
 		super(dbExecutor, lifecycleManager, eventBus);
-		this.privateGroupManager = privateGroupManager;
 		this.groupInvitationManager = groupInvitationManager;
 	}
 
@@ -68,7 +66,7 @@ public class GroupInvitationControllerImpl
 	@Override
 	public void respondToInvitation(final GroupInvitationItem item,
 			final boolean accept,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
index 71c9f830589181c43a61dde66178aed029bf19fd..433c415ecd2deff434608087903f2d82cb78ffc0 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListController.java
@@ -4,6 +4,7 @@ import android.support.annotation.UiThread;
 
 import org.briarproject.android.DestroyableContext;
 import org.briarproject.android.controller.DbController;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.privategroup.GroupMessageHeader;
@@ -27,8 +28,7 @@ public interface GroupListController extends DbController {
 	void loadGroups(
 			ResultExceptionHandler<Collection<GroupItem>, DbException> result);
 
-	void removeGroup(GroupId g,
-			ResultExceptionHandler<Void, DbException> result);
+	void removeGroup(GroupId g, ExceptionHandler<DbException> result);
 
 	void loadAvailableGroups(
 			ResultExceptionHandler<Integer, DbException> result);
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
index d2dc087f3b9a33a94740cca9322dd77926dfb4de..5c86e79f81efb1159c8341241222f6ff659e98f8 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
@@ -4,6 +4,7 @@ import android.support.annotation.CallSuper;
 
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.controller.DbControllerImpl;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.clients.MessageTracker.GroupCount;
 import org.briarproject.api.db.DatabaseExecutor;
@@ -197,7 +198,7 @@ public class GroupListControllerImpl extends DbControllerImpl
 
 	@Override
 	public void removeGroup(final GroupId g,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
@@ -207,7 +208,6 @@ public class GroupListControllerImpl extends DbControllerImpl
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Removing group took " + duration + " ms");
-					handler.onResult(null);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
index 6dbcf3149946709185019dec247f576dcf26a941..6627514bee6bde622967fa8856684ed5e89a9633 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListFragment.java
@@ -18,6 +18,7 @@ import android.view.ViewGroup;
 
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
+import org.briarproject.android.controller.handler.UiExceptionHandler;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.fragment.BaseFragment;
 import org.briarproject.android.privategroup.creation.CreateGroupActivity;
@@ -26,6 +27,8 @@ import org.briarproject.android.privategroup.list.GroupListController.GroupListL
 import org.briarproject.android.privategroup.list.GroupViewHolder.OnGroupRemoveClickListener;
 import org.briarproject.android.view.BriarRecyclerView;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.api.privategroup.GroupMessageHeader;
 import org.briarproject.api.sync.GroupId;
 
@@ -37,6 +40,8 @@ import javax.inject.Inject;
 import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public class GroupListFragment extends BaseFragment implements
 		GroupListListener, OnGroupRemoveClickListener, OnClickListener {
 
@@ -56,8 +61,9 @@ public class GroupListFragment extends BaseFragment implements
 
 	@Nullable
 	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
+	public View onCreateView(LayoutInflater inflater,
+			@Nullable ViewGroup container,
+			@Nullable Bundle savedInstanceState) {
 
 		View v = inflater.inflate(R.layout.list, container, false);
 
@@ -126,12 +132,8 @@ public class GroupListFragment extends BaseFragment implements
 	@Override
 	public void onGroupRemoveClick(GroupItem item) {
 		controller.removeGroup(item.getId(),
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void result) {
-						// handled by GroupRemovedEvent and onGroupRemoved()
-					}
-
+				new UiExceptionHandler<DbException>(this) {
+					// result handled by GroupRemovedEvent and onGroupRemoved()
 					@Override
 					public void onExceptionUi(DbException exception) {
 						// TODO handle error
diff --git a/briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java b/briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java
index 68fc03bc85d7c6463145541af00010d81822bb54..83bb183fa3b7e1990da311e9b4d3e18f44f38bf6 100644
--- a/briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/sharing/BlogInvitationControllerImpl.java
@@ -1,6 +1,6 @@
 package org.briarproject.android.sharing;
 
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.api.blogs.Blog;
 import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.contact.Contact;
@@ -10,6 +10,7 @@ import org.briarproject.api.event.BlogInvitationReceivedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.nullsafety.NotNullByDefault;
 import org.briarproject.api.sharing.SharingInvitationItem;
 import org.briarproject.api.sync.ClientId;
 
@@ -21,7 +22,7 @@ import javax.inject.Inject;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.blogs.BlogManager.CLIENT_ID;
 
-
+@NotNullByDefault
 public class BlogInvitationControllerImpl
 		extends InvitationControllerImpl<SharingInvitationItem>
 		implements BlogInvitationController {
@@ -59,7 +60,7 @@ public class BlogInvitationControllerImpl
 	@Override
 	public void respondToInvitation(final SharingInvitationItem item,
 			final boolean accept,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
diff --git a/briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java b/briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java
index 5f2d255cdb0cc2bea5c7290f48abf22333ebe267..a472ecb4d3033c5f229cf862ab3ee3b6d5157f6b 100644
--- a/briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/sharing/ForumInvitationControllerImpl.java
@@ -1,6 +1,6 @@
 package org.briarproject.android.sharing;
 
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.db.DbException;
@@ -10,6 +10,7 @@ import org.briarproject.api.event.ForumInvitationReceivedEvent;
 import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.nullsafety.NotNullByDefault;
 import org.briarproject.api.sharing.SharingInvitationItem;
 import org.briarproject.api.sync.ClientId;
 
@@ -21,6 +22,7 @@ import javax.inject.Inject;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.forum.ForumManager.CLIENT_ID;
 
+@NotNullByDefault
 public class ForumInvitationControllerImpl
 		extends InvitationControllerImpl<SharingInvitationItem>
 		implements ForumInvitationController {
@@ -58,7 +60,7 @@ public class ForumInvitationControllerImpl
 	@Override
 	public void respondToInvitation(final SharingInvitationItem item,
 			final boolean accept,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationActivity.java b/briar-android/src/org/briarproject/android/sharing/InvitationActivity.java
index 5a17037134a6174dbdb114e118a8f01a47d38351..b398fbd8249cc6747625f0cdf2112bb536d16f3d 100644
--- a/briar-android/src/org/briarproject/android/sharing/InvitationActivity.java
+++ b/briar-android/src/org/briarproject/android/sharing/InvitationActivity.java
@@ -2,16 +2,20 @@ package org.briarproject.android.sharing;
 
 import android.content.Context;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v7.widget.LinearLayoutManager;
 import android.widget.Toast;
 
 import org.briarproject.R;
 import org.briarproject.android.BriarActivity;
+import org.briarproject.android.controller.handler.UiExceptionHandler;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.sharing.InvitationController.InvitationListener;
 import org.briarproject.android.view.BriarRecyclerView;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.api.sharing.InvitationItem;
 
 import java.util.Collection;
@@ -20,6 +24,8 @@ import java.util.logging.Logger;
 import static android.widget.Toast.LENGTH_SHORT;
 import static org.briarproject.android.sharing.InvitationAdapter.InvitationClickListener;
 
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
 public abstract class InvitationActivity<I extends InvitationItem>
 		extends BriarActivity
 		implements InvitationListener, InvitationClickListener<I> {
@@ -31,7 +37,7 @@ public abstract class InvitationActivity<I extends InvitationItem>
 	private BriarRecyclerView list;
 
 	@Override
-	public void onCreate(Bundle state) {
+	public void onCreate(@Nullable Bundle state) {
 		super.onCreate(state);
 
 		setContentView(R.layout.list);
@@ -101,12 +107,7 @@ public abstract class InvitationActivity<I extends InvitationItem>
 	protected void respondToInvitation(final I item,
 			final boolean accept) {
 		getController().respondToInvitation(item, accept,
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void result) {
-
-					}
-
+				new UiExceptionHandler<DbException>(this) {
 					@Override
 					public void onExceptionUi(DbException exception) {
 						// TODO proper error handling
diff --git a/briar-android/src/org/briarproject/android/sharing/InvitationController.java b/briar-android/src/org/briarproject/android/sharing/InvitationController.java
index 5ea5c88e362d7ca84d6338e7e01bab1cd60592d4..a79d0347ad1b14439a7ccf3c0f8f6e0be92bfe9a 100644
--- a/briar-android/src/org/briarproject/android/sharing/InvitationController.java
+++ b/briar-android/src/org/briarproject/android/sharing/InvitationController.java
@@ -1,12 +1,15 @@
 package org.briarproject.android.sharing;
 
 import org.briarproject.android.controller.ActivityLifecycleController;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.nullsafety.NotNullByDefault;
 import org.briarproject.api.sharing.InvitationItem;
 
 import java.util.Collection;
 
+@NotNullByDefault
 public interface InvitationController<I extends InvitationItem>
 		extends ActivityLifecycleController {
 
@@ -14,7 +17,7 @@ public interface InvitationController<I extends InvitationItem>
 			ResultExceptionHandler<Collection<I>, DbException> handler);
 
 	void respondToInvitation(I item, boolean accept,
-			ResultExceptionHandler<Void, DbException> handler);
+			ExceptionHandler<DbException> handler);
 
 	interface InvitationListener {
 
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java b/briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java
index 7152d9d2b37e4a5ee898eeea52c506e86263a91f..4303f3415f85080c0fa9ec5756b871fbb21b0ed6 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareBlogActivity.java
@@ -5,7 +5,7 @@ import android.widget.Toast;
 
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.android.controller.handler.UiExceptionHandler;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
@@ -56,12 +56,7 @@ public class ShareBlogActivity extends ShareActivity {
 	@Override
 	void share(Collection<ContactId> contacts, String msg) {
 		controller.share(groupId, contacts, msg,
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void result) {
-
-					}
-
+				new UiExceptionHandler<DbException>(this) {
 					@Override
 					public void onExceptionUi(DbException exception) {
 						// TODO proper error handling
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java b/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java
index ffaa0ecac9ef41a1e1475d171935c5212b1a3b6c..7e51d99fed7eb394b5f22cebb66fd5442583aa40 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareBlogController.java
@@ -2,7 +2,7 @@ package org.briarproject.android.sharing;
 
 import org.briarproject.android.contactselection.ContactSelectorController;
 import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.sync.GroupId;
@@ -13,6 +13,6 @@ public interface ShareBlogController
 		extends ContactSelectorController<SelectableContactItem> {
 
 	void share(GroupId g, Collection<ContactId> contacts, String msg,
-			ResultExceptionHandler<Void, DbException> handler);
+			ExceptionHandler<DbException> handler);
 
 }
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java b/briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java
index 35e28da6916cf9ab2d6517a34f4e667be48a5dcc..ae0512f6e6e2c866ebf6df0f202ac79f9d16e035 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareBlogControllerImpl.java
@@ -2,7 +2,7 @@ package org.briarproject.android.sharing;
 
 import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
 import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
@@ -65,7 +65,7 @@ public class ShareBlogControllerImpl
 	@Override
 	public void share(final GroupId g, final Collection<ContactId> contacts,
 			final String msg,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java b/briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java
index 7904902d3e531ed405896a5977561939b3826e01..51689bc2f3da60b65f1ae5bcf9e78b99e546d989 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareForumActivity.java
@@ -5,7 +5,7 @@ import android.widget.Toast;
 
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.android.controller.handler.UiExceptionHandler;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
@@ -57,12 +57,7 @@ public class ShareForumActivity extends ShareActivity {
 	@Override
 	void share(Collection<ContactId> contacts, String msg) {
 		controller.share(groupId, contacts, msg,
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void result) {
-
-					}
-
+				new UiExceptionHandler<DbException>(this) {
 					@Override
 					public void onExceptionUi(DbException exception) {
 						// TODO proper error handling
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumController.java b/briar-android/src/org/briarproject/android/sharing/ShareForumController.java
index 000398f5fabe9f49acfdc92b3b601c76d22f8d37..1ad94416a3996adfdadabf6bc86c5a57a695ea60 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumController.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareForumController.java
@@ -2,6 +2,7 @@ package org.briarproject.android.sharing;
 
 import org.briarproject.android.contactselection.ContactSelectorController;
 import org.briarproject.android.contactselection.SelectableContactItem;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
@@ -13,6 +14,6 @@ public interface ShareForumController
 		extends ContactSelectorController<SelectableContactItem> {
 
 	void share(GroupId g, Collection<ContactId> contacts, String msg,
-			ResultExceptionHandler<Void, DbException> handler);
+			ExceptionHandler<DbException> handler);
 
 }
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java b/briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java
index 715250dac7c01aef4c03c3051143ab456f134878..a4500709fd0aa88ee03e3966199096c8bde880c4 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareForumControllerImpl.java
@@ -2,7 +2,7 @@ package org.briarproject.android.sharing;
 
 import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
 import org.briarproject.android.contactselection.SelectableContactItem;
-import org.briarproject.android.controller.handler.ResultExceptionHandler;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
@@ -65,7 +65,7 @@ public class ShareForumControllerImpl
 	@Override
 	public void share(final GroupId g, final Collection<ContactId> contacts,
 			final String msg,
-			final ResultExceptionHandler<Void, DbException> handler) {
+			final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListController.java b/briar-android/src/org/briarproject/android/threaded/ThreadListController.java
index f2e7570a820d89f66cf7e3452d74b3a1a4256514..19e339ea4fcdf0654906610eedfddc2f546d86a5 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListController.java
+++ b/briar-android/src/org/briarproject/android/threaded/ThreadListController.java
@@ -5,6 +5,7 @@ import android.support.annotation.UiThread;
 
 import org.briarproject.android.DestroyableContext;
 import org.briarproject.android.controller.ActivityLifecycleController;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.clients.NamedGroup;
 import org.briarproject.api.clients.PostHeader;
@@ -31,7 +32,7 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem
 	void createAndStoreMessage(String body, @Nullable I parentItem,
 			ResultExceptionHandler<I, DbException> handler);
 
-	void deleteNamedGroup(ResultExceptionHandler<Void, DbException> handler);
+	void deleteNamedGroup(ExceptionHandler<DbException> handler);
 
 	interface ThreadListListener<H> extends DestroyableContext {
 		@UiThread
diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
index 3d52c972fa8b02b8b924570c1ac2e1a07310be64..f0c286aeddd38fce9dad99e329025f8339546bf2 100644
--- a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java
@@ -5,11 +5,12 @@ import android.support.annotation.CallSuper;
 
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.controller.DbControllerImpl;
+import org.briarproject.android.controller.handler.ExceptionHandler;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.android.threaded.ThreadListController.ThreadListListener;
-import org.briarproject.api.clients.ThreadedMessage;
 import org.briarproject.api.clients.NamedGroup;
 import org.briarproject.api.clients.PostHeader;
+import org.briarproject.api.clients.ThreadedMessage;
 import org.briarproject.api.crypto.CryptoExecutor;
 import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.db.DbException;
@@ -265,8 +266,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
 	protected abstract H addLocalMessage(M message) throws DbException;
 
 	@Override
-	public void deleteNamedGroup(
-			final ResultExceptionHandler<Void, DbException> handler) {
+	public void deleteNamedGroup(final ExceptionHandler<DbException> handler) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
@@ -277,8 +277,6 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Removing group took " + duration + " ms");
-					//noinspection ConstantConditions
-					handler.onResult(null);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);