Repository: docker-java/docker-java
Pull request #270 (2015-07-15 09:00:57)

Passing result callbacks for async commands via commands exec() method
Refactored the async commands API (stats, events, log, attach, build, push, pull) so that result callbacks can be passed within the call to exec() method of a command.


Patch:
diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java
index ef16085b..cd276ec1 100644
--- a/src/main/java/com/github/dockerjava/api/DockerClient.java
+++ b/src/main/java/com/github/dockerjava/api/DockerClient.java
@@ -44,8 +44,11 @@ import com.github.dockerjava.api.command.VersionCmd;
 import com.github.dockerjava.api.command.WaitContainerCmd;
 import com.github.dockerjava.api.model.AuthConfig;
 import com.github.dockerjava.api.model.Event;
+import com.github.dockerjava.api.model.BuildResponseItem;
 import com.github.dockerjava.api.model.Frame;
 import com.github.dockerjava.api.model.Identifier;
+import com.github.dockerjava.api.model.PullResponseItem;
+import com.github.dockerjava.api.model.PushResponseItem;
 import com.github.dockerjava.api.model.Statistics;
 
 // https://godoc.org/github.com/fsouza/go-dockerclient
@@ -114,13 +117,13 @@ public interface DockerClient extends Closeable {
 
     public WaitContainerCmd waitContainerCmd(String containerId);
 
-    public AttachContainerCmd attachContainerCmd(String containerId, ResultCallback<Frame> resultCallback);
+    public AttachContainerCmd attachContainerCmd(String containerId);
 
     public ExecStartCmd execStartCmd(String containerId);
 
     public InspectExecCmd inspectExecCmd(String execId);
 
-    public LogContainerCmd logContainerCmd(String containerId, ResultCallback<Frame> resultCallback);
+    public LogContainerCmd logContainerCmd(String containerId);
 
     public CopyFileFromContainerCmd copyFileFromContainerCmd(String containerId, String resource);
 
@@ -148,9 +151,9 @@ public interface DockerClient extends Closeable {
 
     public UnpauseContainerCmd unpauseContainerCmd(String containerId);
 
-    public EventsCmd eventsCmd(ResultCallback<Event> resultCallback);
+    public EventsCmd eventsCmd();
 
-    public StatsCmd statsCmd(ResultCallback<Statistics> resultCallback);
+    public StatsCmd statsCmd();
 
     @Override
     public void close() throws IOException;
diff --git a/src/main/java/com/github/dockerjava/api/async/ResultCallback.java b/src/main/java/com/github/dockerjava/api/async/ResultCallback.java
index fc3e5985..1eb7ebce 100644
--- a/src/main/java/com/github/dockerjava/api/async/ResultCallback.java
+++ b/src/main/java/com/github/dockerjava/api/async/ResultCallback.java
@@ -5,7 +5,7 @@ import java.io.Closeable;
 /**
  * Result callback
  */
-public interface ResultCallback<RES_T> extends Closeable {
+public interface ResultCallback<A_RES_T> extends Closeable {
     /**
      * Called when the async processing starts. The passed {@link Closeable} can be used to close/interrupt the
      * processing
@@ -13,7 +13,7 @@ public interface ResultCallback<RES_T> extends Closeable {
     void onStart(Closeable closeable);
 
     /** Called when an async result event occurs */
-    void onNext(RES_T object);
+    void onNext(A_RES_T object);
 
     /** Called when an exception occurs while processing */
     void onError(Throwable throwable);
diff --git a/src/main/java/com/github/dockerjava/api/command/AsyncDockerCmd.java b/src/main/java/com/github/dockerjava/api/command/AsyncDockerCmd.java
index 4745fae1..fb1b894d 100644
--- a/src/main/java/com/github/dockerjava/api/command/AsyncDockerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/AsyncDockerCmd.java
@@ -11,10 +11,9 @@ import com.github.dockerjava.api.async.ResultCallback;
  * @author marcus
  *
  */
-public interface AsyncDockerCmd<CMD_T extends DockerCmd<RES_T>, A_RES_T, RES_T> extends DockerCmd<RES_T> {
+public interface AsyncDockerCmd<CMD_T extends AsyncDockerCmd<CMD_T, A_RES_T>, A_RES_T> extends DockerCmd<Void> {
 
-    public ResultCallback<A_RES_T> getResultCallback();
 
-    public CMD_T withResultCallback(ResultCallback<A_RES_T> resultCallback);
+    public <T extends ResultCallback<A_RES_T>> T exec(T resultCallback);
 
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/AttachContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/AttachContainerCmd.java
index 3261be28..f837c89c 100644
--- a/src/main/java/com/github/dockerjava/api/command/AttachContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/AttachContainerCmd.java
@@ -3,7 +3,6 @@ package com.github.dockerjava.api.command;
 import java.io.InputStream;
 
 import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.api.model.Frame;
 
 /**
@@ -21,7 +20,7 @@ import com.github.dockerjava.api.model.Frame;
  * @param timestamps
  *            - true or false, if true, print timestamps for every log line. Defaults to false.
  */
-public interface AttachContainerCmd extends AsyncDockerCmd<AttachContainerCmd, Frame, Void> {
+public interface AttachContainerCmd extends AsyncDockerCmd<AttachContainerCmd, Frame> {
 
     public String getContainerId();
 
@@ -63,16 +62,7 @@ public interface AttachContainerCmd extends AsyncDockerCmd<AttachContainerCmd, F
 
     public AttachContainerCmd withLogs();
 
-    /**
-     * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks.
-     *
-     * @throws NotFoundException
-     *             No such container
-     */
-    @Override
-    public Void exec() throws NotFoundException;
-
-    public static interface Exec extends DockerCmdExec<AttachContainerCmd, Void> {
+    public static interface Exec extends DockerCmdAsyncExec<AttachContainerCmd, Frame> {
     }
 
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/AuthCmd.java b/src/main/java/com/github/dockerjava/api/command/AuthCmd.java
index c84fcb3b..26e05c1e 100644
--- a/src/main/java/com/github/dockerjava/api/command/AuthCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/AuthCmd.java
@@ -5,11 +5,11 @@ import com.github.dockerjava.api.model.AuthConfig;
 import com.github.dockerjava.api.model.AuthResponse;
 
 /**
- * 
+ *
  * Authenticate with the server, useful for checking authentication.
- * 
+ *
  */
-public interface AuthCmd extends DockerCmd<AuthResponse> {
+public interface AuthCmd extends SyncDockerCmd<AuthResponse> {
 
     public AuthConfig getAuthConfig();
 
@@ -24,7 +24,7 @@ public interface AuthCmd extends DockerCmd<AuthResponse> {
     @Override
     public AuthResponse exec() throws UnauthorizedException;
 
-    public static interface Exec extends DockerCmdExec<AuthCmd, AuthResponse> {
+    public static interface Exec extends DockerCmdSyncExec<AuthCmd, AuthResponse> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java
index 5dd1cc17..5fd6015c 100644
--- a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java
@@ -1,20 +1,19 @@
 package com.github.dockerjava.api.command;
 
-import com.github.dockerjava.api.model.AuthConfigurations;
-import com.github.dockerjava.api.model.EventStreamItem;
-
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 
+import com.github.dockerjava.api.model.AuthConfigurations;
+import com.github.dockerjava.api.model.BuildResponseItem;
+
 /**
- * 
+ *
  * Build an image from Dockerfile.
- * 
+ *
  * TODO: http://docs.docker.com/reference/builder/#dockerignore
- * 
+ *
  */
-public interface BuildImageCmd extends DockerCmd<BuildImageCmd.Response> {
+public interface BuildImageCmd extends AsyncDockerCmd<BuildImageCmd, BuildResponseItem> {
 
     public BuildImageCmd withTag(String tag);
 
@@ -58,14 +57,9 @@ public interface BuildImageCmd extends DockerCmd<BuildImageCmd.Response> {
 
     public BuildImageCmd withBuildAuthConfigs(AuthConfigurations authConfig);
 
-    public static interface Exec extends DockerCmdExec<BuildImageCmd, BuildImageCmd.Response> {
+    public static interface Exec extends DockerCmdAsyncExec<BuildImageCmd, BuildResponseItem> {
     }
 
-    /**
-     * @see {@link com.github.dockerjava.core.command.EventStreamReader}
-     */
-    public static abstract class Response extends InputStream {
-        public abstract Iterable<EventStreamItem> getItems() throws IOException;
-    }
+
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/CommitCmd.java b/src/main/java/com/github/dockerjava/api/command/CommitCmd.java
index 2c24a0f4..10de6645 100644
--- a/src/main/java/com/github/dockerjava/api/command/CommitCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/CommitCmd.java
@@ -9,7 +9,7 @@ import com.github.dockerjava.api.model.Volumes;
  * Create a new image from a container's changes. Returns the new image ID.
  *
  */
-public interface CommitCmd extends DockerCmd<String> {
+public interface CommitCmd extends SyncDockerCmd<String> {
 
     public String getContainerId();
 
@@ -110,7 +110,7 @@ public interface CommitCmd extends DockerCmd<String> {
     @Override
     public String exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<CommitCmd, String> {
+    public static interface Exec extends DockerCmdSyncExec<CommitCmd, String> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/ContainerDiffCmd.java b/src/main/java/com/github/dockerjava/api/command/ContainerDiffCmd.java
index ed702846..968fb5c7 100644
--- a/src/main/java/com/github/dockerjava/api/command/ContainerDiffCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/ContainerDiffCmd.java
@@ -7,7 +7,7 @@ import com.github.dockerjava.api.InternalServerErrorException;
 import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.api.model.ChangeLog;
 
-public interface ContainerDiffCmd extends DockerCmd<List<ChangeLog>> {
+public interface ContainerDiffCmd extends SyncDockerCmd<List<ChangeLog>> {
 
     public String getContainerId();
 
@@ -27,7 +27,7 @@ public interface ContainerDiffCmd extends DockerCmd<List<ChangeLog>> {
     @Override
     public List<ChangeLog> exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<ContainerDiffCmd, List<ChangeLog>> {
+    public static interface Exec extends DockerCmdSyncExec<ContainerDiffCmd, List<ChangeLog>> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java
index eb67dfbd..1bc3ca90 100644
--- a/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/CopyFileFromContainerCmd.java
@@ -4,7 +4,7 @@ import java.io.InputStream;
 
 import com.github.dockerjava.api.NotFoundException;
 
-public interface CopyFileFromContainerCmd extends DockerCmd<InputStream> {
+public interface CopyFileFromContainerCmd extends SyncDockerCmd<InputStream> {
 
     public String getContainerId();
 
@@ -20,14 +20,14 @@ public interface CopyFileFromContainerCmd extends DockerCmd<InputStream> {
 
     /**
      * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks.
-     * 
+     *
      * @throws NotFoundException
      *             No such container
      */
     @Override
     public InputStream exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<CopyFileFromContainerCmd, InputStream> {
+    public static interface Exec extends DockerCmdSyncExec<CopyFileFromContainerCmd, InputStream> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java
index 9ad44b2c..37177441 100644
--- a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java
@@ -17,9 +17,9 @@ import com.github.dockerjava.api.model.RestartPolicy;
 import com.github.dockerjava.api.model.Volume;
 import com.github.dockerjava.api.model.VolumesFrom;
 
-public interface CreateContainerCmd extends DockerCmd<CreateContainerResponse> {
+public interface CreateContainerCmd extends SyncDockerCmd<CreateContainerResponse> {
 
-    public static interface Exec extends DockerCmdExec<CreateContainerCmd, CreateContainerResponse> {
+    public static interface Exec extends DockerCmdSyncExec<CreateContainerCmd, CreateContainerResponse> {
     }
 
     /**
diff --git a/src/main/java/com/github/dockerjava/api/command/CreateImageCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateImageCmd.java
index a25535d5..93b00efa 100644
--- a/src/main/java/com/github/dockerjava/api/command/CreateImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/CreateImageCmd.java
@@ -2,7 +2,7 @@ package com.github.dockerjava.api.command;
 
 import java.io.InputStream;
 
-public interface CreateImageCmd extends DockerCmd<CreateImageResponse> {
+public interface CreateImageCmd extends SyncDockerCmd<CreateImageResponse> {
 
     public String getRepository();
 
@@ -30,7 +30,7 @@ public interface CreateImageCmd extends DockerCmd<CreateImageResponse> {
      */
     public CreateImageCmd withTag(String tag);
 
-    public static interface Exec extends DockerCmdExec<CreateImageCmd, CreateImageResponse> {
+    public static interface Exec extends DockerCmdSyncExec<CreateImageCmd, CreateImageResponse> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmd.java b/src/main/java/com/github/dockerjava/api/command/DockerCmd.java
index 79236b89..ba9992be 100644
--- a/src/main/java/com/github/dockerjava/api/command/DockerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/DockerCmd.java
@@ -4,6 +4,6 @@ import java.io.Closeable;
 
 public interface DockerCmd<RES_T> extends Closeable {
 
-    public RES_T exec();
+
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmdAsyncExec.java b/src/main/java/com/github/dockerjava/api/command/DockerCmdAsyncExec.java
new file mode 100644
index 00000000..dfd2a371
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdAsyncExec.java
@@ -0,0 +1,9 @@
+package com.github.dockerjava.api.command;
+
+import com.github.dockerjava.api.async.ResultCallback;
+
+public interface DockerCmdAsyncExec<CMD_T extends DockerCmd<Void>, A_RES_T> {
+
+    public Void exec(CMD_T command, ResultCallback<A_RES_T> resultCallback);
+
+}
diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmdExec.java b/src/main/java/com/github/dockerjava/api/command/DockerCmdSyncExec.java
similarity index 53%
rename from src/main/java/com/github/dockerjava/api/command/DockerCmdExec.java
rename to src/main/java/com/github/dockerjava/api/command/DockerCmdSyncExec.java
index 635395ed..678b4afe 100644
--- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdSyncExec.java
@@ -1,6 +1,6 @@
 package com.github.dockerjava.api.command;
 
-public interface DockerCmdExec<CMD_T extends DockerCmd<RES_T>, RES_T> {
+public interface DockerCmdSyncExec<CMD_T extends DockerCmd<RES_T>, RES_T> {
 
     public RES_T exec(CMD_T command);
 
diff --git a/src/main/java/com/github/dockerjava/api/command/EventsCmd.java b/src/main/java/com/github/dockerjava/api/command/EventsCmd.java
index 057bed64..cbcd122a 100644
--- a/src/main/java/com/github/dockerjava/api/command/EventsCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/EventsCmd.java
@@ -10,7 +10,7 @@ import com.github.dockerjava.api.model.Event;
  * @param until
  *            - Stream events until this timestamp
  */
-public interface EventsCmd extends AsyncDockerCmd<EventsCmd, Event, Void> {
+public interface EventsCmd extends AsyncDockerCmd<EventsCmd, Event> {
     public EventsCmd withSince(String since);
 
     public EventsCmd withUntil(String until);
@@ -19,6 +19,6 @@ public interface EventsCmd extends AsyncDockerCmd<EventsCmd, Event, Void> {
 
     public String getUntil();
 
-    public static interface Exec extends DockerCmdExec<EventsCmd, Void> {
+    public static interface Exec extends DockerCmdAsyncExec<EventsCmd, Event> {
     }
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java b/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java
index ffeef015..8094f371 100644
--- a/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/ExecCreateCmd.java
@@ -1,6 +1,6 @@
 package com.github.dockerjava.api.command;
 
-public interface ExecCreateCmd extends DockerCmd<ExecCreateCmdResponse> {
+public interface ExecCreateCmd extends SyncDockerCmd<ExecCreateCmdResponse> {
 
     public String getContainerId();
 
@@ -32,6 +32,6 @@ public interface ExecCreateCmd extends DockerCmd<ExecCreateCmdResponse> {
 
     public boolean hasTtyEnabled();
 
-    public static interface Exec extends DockerCmdExec<ExecCreateCmd, ExecCreateCmdResponse> {
+    public static interface Exec extends DockerCmdSyncExec<ExecCreateCmd, ExecCreateCmdResponse> {
     }
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/ExecStartCmd.java b/src/main/java/com/github/dockerjava/api/command/ExecStartCmd.java
index 339e2c9a..cd9eaa01 100644
--- a/src/main/java/com/github/dockerjava/api/command/ExecStartCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/ExecStartCmd.java
@@ -4,7 +4,7 @@ import com.github.dockerjava.api.NotFoundException;
 
 import java.io.InputStream;
 
-public interface ExecStartCmd extends DockerCmd<InputStream> {
+public interface ExecStartCmd extends SyncDockerCmd<InputStream> {
 
     public String getExecId();
 
@@ -24,13 +24,13 @@ public interface ExecStartCmd extends DockerCmd<InputStream> {
 
     /**
      * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks.
-     * 
+     *
      * @throws com.github.dockerjava.api.NotFoundException
      *             No such exec instance
      */
     @Override
     public InputStream exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<ExecStartCmd, InputStream> {
+    public static interface Exec extends DockerCmdSyncExec<ExecStartCmd, InputStream> {
     }
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/InfoCmd.java b/src/main/java/com/github/dockerjava/api/command/InfoCmd.java
index 10e3597e..2fe7f2bf 100644
--- a/src/main/java/com/github/dockerjava/api/command/InfoCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/InfoCmd.java
@@ -2,9 +2,9 @@ package com.github.dockerjava.api.command;
 
 import com.github.dockerjava.api.model.Info;
 
-public interface InfoCmd extends DockerCmd<Info> {
+public interface InfoCmd extends SyncDockerCmd<Info> {
 
-    public static interface Exec extends DockerCmdExec<InfoCmd, Info> {
+    public static interface Exec extends DockerCmdSyncExec<InfoCmd, Info> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java
index e0d08784..d9988085 100644
--- a/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/InspectContainerCmd.java
@@ -2,7 +2,7 @@ package com.github.dockerjava.api.command;
 
 import com.github.dockerjava.api.NotFoundException;
 
-public interface InspectContainerCmd extends DockerCmd<InspectContainerResponse> {
+public interface InspectContainerCmd extends SyncDockerCmd<InspectContainerResponse> {
 
     public String getContainerId();
 
@@ -15,7 +15,7 @@ public interface InspectContainerCmd extends DockerCmd<InspectContainerResponse>
     @Override
     public InspectContainerResponse exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<InspectContainerCmd, InspectContainerResponse> {
+    public static interface Exec extends DockerCmdSyncExec<InspectContainerCmd, InspectContainerResponse> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java b/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java
index 82243614..36ce45fc 100644
--- a/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java
@@ -2,7 +2,7 @@ package com.github.dockerjava.api.command;
 
 import com.github.dockerjava.api.NotFoundException;
 
-public interface InspectExecCmd extends DockerCmd<InspectExecResponse> {
+public interface InspectExecCmd extends SyncDockerCmd<InspectExecResponse> {
     public String getExecId();
 
     public InspectExecCmd withExecId(String execId);
@@ -14,6 +14,6 @@ public interface InspectExecCmd extends DockerCmd<InspectExecResponse> {
     @Override
     public InspectExecResponse exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<InspectExecCmd, InspectExecResponse> {
+    public static interface Exec extends DockerCmdSyncExec<InspectExecCmd, InspectExecResponse> {
     }
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/InspectImageCmd.java b/src/main/java/com/github/dockerjava/api/command/InspectImageCmd.java
index ebf6550d..6eaea907 100644
--- a/src/main/java/com/github/dockerjava/api/command/InspectImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/InspectImageCmd.java
@@ -5,7 +5,7 @@ import com.github.dockerjava.api.NotFoundException;
 /**
  * Inspect the details of an image.
  */
-public interface InspectImageCmd extends DockerCmd<InspectImageResponse> {
+public interface InspectImageCmd extends SyncDockerCmd<InspectImageResponse> {
 
     public String getImageId();
 
@@ -18,7 +18,7 @@ public interface InspectImageCmd extends DockerCmd<InspectImageResponse> {
     @Override
     public InspectImageResponse exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<InspectImageCmd, InspectImageResponse> {
+    public static interface Exec extends DockerCmdSyncExec<InspectImageCmd, InspectImageResponse> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/KillContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/KillContainerCmd.java
index 33fceba3..513bf09c 100644
--- a/src/main/java/com/github/dockerjava/api/command/KillContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/KillContainerCmd.java
@@ -5,7 +5,7 @@ import com.github.dockerjava.api.NotFoundException;
 /**
  * Kill a running container.
  */
-public interface KillContainerCmd extends DockerCmd<Void> {
+public interface KillContainerCmd extends SyncDockerCmd<Void> {
 
     public String getContainerId();
 
@@ -22,7 +22,7 @@ public interface KillContainerCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<KillContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<KillContainerCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java b/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java
index c2a116be..5cba1175 100644
--- a/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java
@@ -20,7 +20,7 @@ import com.github.dockerjava.api.model.Filters;
  *            - Show only containers created before Id, include non-running ones.
  *
  */
-public interface ListContainersCmd extends DockerCmd<List<Container>> {
+public interface ListContainersCmd extends SyncDockerCmd<List<Container>> {
 
     public int getLimit();
 
@@ -46,7 +46,7 @@ public interface ListContainersCmd extends DockerCmd<List<Container>> {
 
     public ListContainersCmd withFilters(Filters filters);
 
-    public static interface Exec extends DockerCmdExec<ListContainersCmd, List<Container>> {
+    public static interface Exec extends DockerCmdSyncExec<ListContainersCmd, List<Container>> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java b/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java
index 4c6a899c..170ed810 100644
--- a/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java
@@ -12,7 +12,7 @@ import com.github.dockerjava.api.model.Image;
  * @param filters
  *            - a json encoded value of the filters (a map[string][]string) to process on the images list.
  */
-public interface ListImagesCmd extends DockerCmd<List<Image>> {
+public interface ListImagesCmd extends SyncDockerCmd<List<Image>> {
 
     public String getFilters();
 
@@ -22,7 +22,7 @@ public interface ListImagesCmd extends DockerCmd<List<Image>> {
 
     public ListImagesCmd withFilters(String filters);
 
-    public static interface Exec extends DockerCmdExec<ListImagesCmd, List<Image>> {
+    public static interface Exec extends DockerCmdSyncExec<ListImagesCmd, List<Image>> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java
index a0e9d6ba..a97393aa 100644
--- a/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/LogContainerCmd.java
@@ -1,11 +1,10 @@
 package com.github.dockerjava.api.command;
 
+import java.io.InputStream;
+
 import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.api.model.Frame;
 
-import java.io.InputStream;
-
 /**
  * Get container logs
  *
@@ -20,7 +19,7 @@ import java.io.InputStream;
  * @param tail
  *            - `all` or `<number>`, Output specified number of lines at the end of logs
  */
-public interface LogContainerCmd extends AsyncDockerCmd<LogContainerCmd, Frame, Void> {
+public interface LogContainerCmd extends AsyncDockerCmd<LogContainerCmd, Frame> {
 
     public String getContainerId();
 
@@ -64,16 +63,7 @@ public interface LogContainerCmd extends AsyncDockerCmd<LogContainerCmd, Frame,
 
     public LogContainerCmd withTail(int tail);
 
-    /**
-     * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks.
-     *
-     * @throws NotFoundException
-     *             No such container
-     */
-    @Override
-    public Void exec() throws NotFoundException;
-
-    public static interface Exec extends DockerCmdExec<LogContainerCmd, Void> {
+    public static interface Exec extends DockerCmdAsyncExec<LogContainerCmd, Frame> {
     }
 
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/PauseContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/PauseContainerCmd.java
index a052c8bc..21039bb4 100644
--- a/src/main/java/com/github/dockerjava/api/command/PauseContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/PauseContainerCmd.java
@@ -9,7 +9,7 @@ import com.github.dockerjava.api.NotFoundException;
  *            - Id of the container
  *
  */
-public interface PauseContainerCmd extends DockerCmd<Void> {
+public interface PauseContainerCmd extends SyncDockerCmd<Void> {
 
     public String getContainerId();
 
@@ -22,7 +22,7 @@ public interface PauseContainerCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<PauseContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<PauseContainerCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/PingCmd.java b/src/main/java/com/github/dockerjava/api/command/PingCmd.java
index a5d88056..0be834e9 100644
--- a/src/main/java/com/github/dockerjava/api/command/PingCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/PingCmd.java
@@ -2,11 +2,11 @@ package com.github.dockerjava.api.command;
 
 /**
  * Ping the Docker server
- * 
+ *
  */
-public interface PingCmd extends DockerCmd<Void> {
+public interface PingCmd extends SyncDockerCmd<Void> {
 
-    public static interface Exec extends DockerCmdExec<PingCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<PingCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java b/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java
index b3e6db6a..53edbe9a 100644
--- a/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java
@@ -1,16 +1,14 @@
 package com.github.dockerjava.api.command;
 
 import com.github.dockerjava.api.model.AuthConfig;
-import com.github.dockerjava.core.command.EventStreamReader;
-
-import java.io.InputStream;
+import com.github.dockerjava.api.model.PullResponseItem;
 
 /**
  *
  * Pull image from repository.
  *
  */
-public interface PullImageCmd extends DockerCmd<InputStream> {
+public interface PullImageCmd extends AsyncDockerCmd<PullImageCmd, PullResponseItem> {
 
     public String getRepository();
 
@@ -28,15 +26,6 @@ public interface PullImageCmd extends DockerCmd<InputStream> {
 
     public PullImageCmd withAuthConfig(AuthConfig authConfig);
 
-    public static interface Exec extends DockerCmdExec<PullImageCmd, InputStream> {
+    public static interface Exec extends DockerCmdAsyncExec<PullImageCmd, PullResponseItem> {
     }
-
-    /**
-     * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks.
-     *
-     * @see {@link EventStreamReader}
-     */
-    @Override
-    public InputStream exec();
-
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/PushImageCmd.java b/src/main/java/com/github/dockerjava/api/command/PushImageCmd.java
index 6b9a67eb..9b8c5591 100644
--- a/src/main/java/com/github/dockerjava/api/command/PushImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/PushImageCmd.java
@@ -1,12 +1,9 @@
 package com.github.dockerjava.api.command;
 
 import com.github.dockerjava.api.NotFoundException;
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.model.AuthConfig;
-import com.github.dockerjava.api.model.PushEventStreamItem;
-import com.github.dockerjava.core.command.EventStreamReader;
-
-import java.io.IOException;
-import java.io.InputStream;
+import com.github.dockerjava.api.model.PushResponseItem;
 
 /**
  * Push the latest image to the repository.
@@ -14,7 +11,7 @@ import java.io.InputStream;
  * @param name
  *            The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
  */
-public interface PushImageCmd extends DockerCmd<PushImageCmd.Response> {
+public interface PushImageCmd extends AsyncDockerCmd<PushImageCmd, PushResponseItem> {
 
     public String getName();
 
@@ -40,16 +37,9 @@ public interface PushImageCmd extends DockerCmd<PushImageCmd.Response> {
      * @throws NotFoundException
      *             No such image
      */
-    public Response exec() throws NotFoundException;
-
-    public static interface Exec extends DockerCmdExec<PushImageCmd, Response> {
-    }
+    @Override
+    public <T extends ResultCallback<PushResponseItem>> T exec(T resultCallback);
 
-    /**
-     * @see {@link EventStreamReader}
-     */
-    public static abstract class Response extends InputStream {
-        public abstract Iterable<PushEventStreamItem> getItems() throws IOException;
+    public static interface Exec extends DockerCmdAsyncExec<PushImageCmd, PushResponseItem> {
     }
-
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/RemoveContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/RemoveContainerCmd.java
index 9f917a32..fe5378dc 100644
--- a/src/main/java/com/github/dockerjava/api/command/RemoveContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/RemoveContainerCmd.java
@@ -4,13 +4,13 @@ import com.github.dockerjava.api.NotFoundException;
 
 /**
  * Remove a container.
- * 
+ *
  * @param removeVolumes
  *            - true or false, Remove the volumes associated to the container. Defaults to false
  * @param force
  *            - true or false, Removes the container even if it was running. Defaults to false
  */
-public interface RemoveContainerCmd extends DockerCmd<Void> {
+public interface RemoveContainerCmd extends SyncDockerCmd<Void> {
 
     public String getContainerId();
 
@@ -33,7 +33,7 @@ public interface RemoveContainerCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<RemoveContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<RemoveContainerCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/RemoveImageCmd.java b/src/main/java/com/github/dockerjava/api/command/RemoveImageCmd.java
index 1ce1cd21..99f2835f 100644
--- a/src/main/java/com/github/dockerjava/api/command/RemoveImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/RemoveImageCmd.java
@@ -7,7 +7,7 @@ import com.github.dockerjava.api.NotFoundException;
  * Remove an image, deleting any tags it might have.
  *
  */
-public interface RemoveImageCmd extends DockerCmd<Void> {
+public interface RemoveImageCmd extends SyncDockerCmd<Void> {
 
     public String getImageId();
 
@@ -34,7 +34,7 @@ public interface RemoveImageCmd extends DockerCmd<Void> {
 
     /**
      * noprune parameter to prevent the deletion of parent images
-     * 
+     *
      */
     public RemoveImageCmd withNoPrune(boolean noPrune);
 
@@ -45,7 +45,7 @@ public interface RemoveImageCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<RemoveImageCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<RemoveImageCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java
index aa07fffd..c2a5219a 100644
--- a/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java
@@ -9,7 +9,7 @@ import com.github.dockerjava.api.NotFoundException;
  *            - Timeout in seconds before killing the container. Defaults to 10 seconds.
  *
  */
-public interface RestartContainerCmd extends DockerCmd<Void> {
+public interface RestartContainerCmd extends SyncDockerCmd<Void> {
 
     public String getContainerId();
 
@@ -26,7 +26,7 @@ public interface RestartContainerCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<RestartContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<RestartContainerCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/SaveImageCmd.java b/src/main/java/com/github/dockerjava/api/command/SaveImageCmd.java
index 67425ab6..0b027a76 100644
--- a/src/main/java/com/github/dockerjava/api/command/SaveImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/SaveImageCmd.java
@@ -4,7 +4,7 @@ import com.github.dockerjava.api.NotFoundException;
 
 import java.io.InputStream;
 
-public interface SaveImageCmd extends DockerCmd<InputStream> {
+public interface SaveImageCmd extends SyncDockerCmd<InputStream> {
 
     public String getName();
 
@@ -24,13 +24,13 @@ public interface SaveImageCmd extends DockerCmd<InputStream> {
 
     /**
      * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks.
-     * 
+     *
      * @throws com.github.dockerjava.api.NotFoundException
      *             No such image
      */
     public InputStream exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<SaveImageCmd, InputStream> {
+    public static interface Exec extends DockerCmdSyncExec<SaveImageCmd, InputStream> {
     }
 
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/SearchImagesCmd.java b/src/main/java/com/github/dockerjava/api/command/SearchImagesCmd.java
index 9279272d..a1229da9 100644
--- a/src/main/java/com/github/dockerjava/api/command/SearchImagesCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/SearchImagesCmd.java
@@ -11,13 +11,13 @@ import com.github.dockerjava.api.model.SearchItem;
  *            - search term
  *
  */
-public interface SearchImagesCmd extends DockerCmd<List<SearchItem>> {
+public interface SearchImagesCmd extends SyncDockerCmd<List<SearchItem>> {
 
     public String getTerm();
 
     public SearchImagesCmd withTerm(String term);
 
-    public static interface Exec extends DockerCmdExec<SearchImagesCmd, List<SearchItem>> {
+    public static interface Exec extends DockerCmdSyncExec<SearchImagesCmd, List<SearchItem>> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/StartContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/StartContainerCmd.java
index 2195e1ec..0cfb3ea8 100644
--- a/src/main/java/com/github/dockerjava/api/command/StartContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/StartContainerCmd.java
@@ -7,9 +7,9 @@ import com.github.dockerjava.api.NotModifiedException;
  * Start a container.
  *
  */
-public interface StartContainerCmd extends DockerCmd<Void> {
+public interface StartContainerCmd extends SyncDockerCmd<Void> {
 
-    public static interface Exec extends DockerCmdExec<StartContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<StartContainerCmd, Void> {
     }
 
     String getContainerId();
diff --git a/src/main/java/com/github/dockerjava/api/command/StatsCmd.java b/src/main/java/com/github/dockerjava/api/command/StatsCmd.java
index f394d7f3..64b38d47 100644
--- a/src/main/java/com/github/dockerjava/api/command/StatsCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/StatsCmd.java
@@ -6,11 +6,11 @@ import com.github.dockerjava.api.model.Statistics;
  * Get container stats. The result of {@link Statistics} is handled asynchronously because the docker remote API will
  * block when a container is stopped until the container is up again.
  */
-public interface StatsCmd extends AsyncDockerCmd<StatsCmd, Statistics, Void> {
+public interface StatsCmd extends AsyncDockerCmd<StatsCmd, Statistics> {
     public StatsCmd withContainerId(String containerId);
 
     public String getContainerId();
 
-    public static interface Exec extends DockerCmdExec<StatsCmd, Void> {
+    public static interface Exec extends DockerCmdAsyncExec<StatsCmd, Statistics> {
     }
 }
diff --git a/src/main/java/com/github/dockerjava/api/command/StopContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/StopContainerCmd.java
index d5bf2e61..dc620b69 100644
--- a/src/main/java/com/github/dockerjava/api/command/StopContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/StopContainerCmd.java
@@ -12,7 +12,7 @@ import com.github.dockerjava.api.NotModifiedException;
  *            - Timeout in seconds before killing the container. Defaults to 10 seconds.
  *
  */
-public interface StopContainerCmd extends DockerCmd<Void> {
+public interface StopContainerCmd extends SyncDockerCmd<Void> {
 
     public String getContainerId();
 
@@ -31,7 +31,7 @@ public interface StopContainerCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException, NotModifiedException;
 
-    public static interface Exec extends DockerCmdExec<StopContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<StopContainerCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/SyncDockerCmd.java b/src/main/java/com/github/dockerjava/api/command/SyncDockerCmd.java
new file mode 100644
index 00000000..7192e46f
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/api/command/SyncDockerCmd.java
@@ -0,0 +1,8 @@
+package com.github.dockerjava.api.command;
+
+
+public interface SyncDockerCmd<RES_T> extends DockerCmd<RES_T> {
+
+    public RES_T exec();
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/TagImageCmd.java b/src/main/java/com/github/dockerjava/api/command/TagImageCmd.java
index 44fd588f..21895e35 100644
--- a/src/main/java/com/github/dockerjava/api/command/TagImageCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/TagImageCmd.java
@@ -9,9 +9,9 @@ package com.github.dockerjava.api.command;
  *            The repository to tag in
  * @param force
  *            (not documented)
- * 
+ *
  */
-public interface TagImageCmd extends DockerCmd<Void> {
+public interface TagImageCmd extends SyncDockerCmd<Void> {
 
     public String getImageId();
 
@@ -31,7 +31,7 @@ public interface TagImageCmd extends DockerCmd<Void> {
 
     public TagImageCmd withForce(boolean force);
 
-    public static interface Exec extends DockerCmdExec<TagImageCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<TagImageCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/TopContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/TopContainerCmd.java
index cc7e33aa..3e1762f1 100644
--- a/src/main/java/com/github/dockerjava/api/command/TopContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/TopContainerCmd.java
@@ -5,7 +5,7 @@ import com.github.dockerjava.api.NotFoundException;
 /**
  * List processes running inside a container
  */
-public interface TopContainerCmd extends DockerCmd<TopContainerResponse> {
+public interface TopContainerCmd extends SyncDockerCmd<TopContainerResponse> {
 
     public String getContainerId();
 
@@ -22,7 +22,7 @@ public interface TopContainerCmd extends DockerCmd<TopContainerResponse> {
     @Override
     public TopContainerResponse exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<TopContainerCmd, TopContainerResponse> {
+    public static interface Exec extends DockerCmdSyncExec<TopContainerCmd, TopContainerResponse> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/UnpauseContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/UnpauseContainerCmd.java
index 44219141..44f5658e 100644
--- a/src/main/java/com/github/dockerjava/api/command/UnpauseContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/UnpauseContainerCmd.java
@@ -9,7 +9,7 @@ import com.github.dockerjava.api.NotFoundException;
  *            - Id of the container
  *
  */
-public interface UnpauseContainerCmd extends DockerCmd<Void> {
+public interface UnpauseContainerCmd extends SyncDockerCmd<Void> {
 
     public String getContainerId();
 
@@ -22,7 +22,7 @@ public interface UnpauseContainerCmd extends DockerCmd<Void> {
     @Override
     public Void exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<UnpauseContainerCmd, Void> {
+    public static interface Exec extends DockerCmdSyncExec<UnpauseContainerCmd, Void> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/VersionCmd.java b/src/main/java/com/github/dockerjava/api/command/VersionCmd.java
index 70352462..5f823c6c 100644
--- a/src/main/java/com/github/dockerjava/api/command/VersionCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/VersionCmd.java
@@ -5,9 +5,9 @@ import com.github.dockerjava.api.model.Version;
 /**
  * Returns the Docker version info.
  */
-public interface VersionCmd extends DockerCmd<Version> {
+public interface VersionCmd extends SyncDockerCmd<Version> {
 
-    public static interface Exec extends DockerCmdExec<VersionCmd, Version> {
+    public static interface Exec extends DockerCmdSyncExec<VersionCmd, Version> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java
index 8841b08a..2accc3af 100644
--- a/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java
+++ b/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java
@@ -4,10 +4,10 @@ import com.github.dockerjava.api.NotFoundException;
 
 /**
  * Wait a container
- * 
+ *
  * Block until container stops, then returns its exit code
  */
-public interface WaitContainerCmd extends DockerCmd<Integer> {
+public interface WaitContainerCmd extends SyncDockerCmd<Integer> {
 
     public String getContainerId();
 
@@ -20,7 +20,7 @@ public interface WaitContainerCmd extends DockerCmd<Integer> {
     @Override
     public Integer exec() throws NotFoundException;
 
-    public static interface Exec extends DockerCmdExec<WaitContainerCmd, Integer> {
+    public static interface Exec extends DockerCmdSyncExec<WaitContainerCmd, Integer> {
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java b/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java
new file mode 100644
index 00000000..c999652e
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/api/model/BuildResponseItem.java
@@ -0,0 +1,20 @@
+package com.github.dockerjava.api.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Represents a build response stream item
+ */
+@JsonIgnoreProperties(ignoreUnknown = false)
+public class BuildResponseItem extends ResponseItem {
+
+    private static final long serialVersionUID = -1252904184236343612L;
+
+    @JsonProperty("stream")
+    private String stream;
+
+    public String getStream() {
+        return stream;
+    }
+}
diff --git a/src/main/java/com/github/dockerjava/api/model/EventStreamItem.java b/src/main/java/com/github/dockerjava/api/model/EventStreamItem.java
deleted file mode 100644
index 9c748981..00000000
--- a/src/main/java/com/github/dockerjava/api/model/EventStreamItem.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.github.dockerjava.api.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.io.Serializable;
-
-import com.google.common.base.Objects;
-
-/**
- * Represents an event stream
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class EventStreamItem implements Serializable {
-
-    private static final long serialVersionUID = 638778515773898651L;
-
-    @JsonProperty("stream")
-    private String stream;
-
-    // {"error":"Error...", "errorDetail":{"code": 123, "message": "Error..."}}
-    @JsonProperty("error")
-    private String error;
-
-    @JsonProperty("errorDetail")
-    private ErrorDetail errorDetail;
-
-    public String getStream() {
-        return stream;
-    }
-
-    public String getError() {
-        return error;
-    }
-
-    public ErrorDetail getErrorDetail() {
-        return errorDetail;
-    }
-
-    @JsonIgnoreProperties(ignoreUnknown = true)
-    public static class ErrorDetail implements Serializable {
-        @JsonProperty("code")
-        String code;
-
-        @JsonProperty("message")
-        String message;
-
-        @Override
-        public String toString() {
-            return Objects.toStringHelper(this).add("code", code).add("message", message).toString();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return Objects.toStringHelper(this).add("stream", stream).add("error", error).add("errorDetail", errorDetail)
-                .toString();
-    }
-}
diff --git a/src/main/java/com/github/dockerjava/api/model/PullEventStreamItem.java b/src/main/java/com/github/dockerjava/api/model/PullEventStreamItem.java
deleted file mode 100644
index cd49e846..00000000
--- a/src/main/java/com/github/dockerjava/api/model/PullEventStreamItem.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.github.dockerjava.api.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Objects;
-
-import java.io.Serializable;
-
-/**
- * Represents an item returned from pull
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class PullEventStreamItem implements Serializable {
-
-    private static final long serialVersionUID = -5187169652557467828L;
-
-    @JsonProperty("status")
-    private String status;
-
-    @JsonProperty("progress")
-    private String progress;
-
-    @JsonProperty("progressDetail")
-    private ProgressDetail progressDetail;
-
-    public String getStatus() {
-        return status;
-    }
-
-    public String getProgress() {
-        return progress;
-    }
-
-    public ProgressDetail getProgressDetail() {
-        return progressDetail;
-    }
-
-    @JsonIgnoreProperties(ignoreUnknown = true)
-    public static class ProgressDetail implements Serializable {
-        @JsonProperty("current")
-        int current;
-
-        @Override
-        public String toString() {
-            return "current " + current;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return Objects.toStringHelper(this).add("status", status).add("progress", progress)
-                .add("progressDetail", progressDetail).toString();
-    }
-}
diff --git a/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java b/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java
new file mode 100644
index 00000000..cb856a11
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java
@@ -0,0 +1,13 @@
+package com.github.dockerjava.api.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * Represents a pull response stream item
+ */
+@JsonIgnoreProperties(ignoreUnknown = false)
+public class PullResponseItem extends ResponseItem {
+
+    private static final long serialVersionUID = 6316219017613249047L;
+
+}
diff --git a/src/main/java/com/github/dockerjava/api/model/PushEventStreamItem.java b/src/main/java/com/github/dockerjava/api/model/PushEventStreamItem.java
deleted file mode 100644
index e022f0c1..00000000
--- a/src/main/java/com/github/dockerjava/api/model/PushEventStreamItem.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.github.dockerjava.api.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.io.Serializable;
-
-import com.google.common.base.Objects;
-
-/**
- * Represents an item returned from push
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class PushEventStreamItem implements Serializable {
-
-    private static final long serialVersionUID = -5187169652557467828L;
-
-    @JsonProperty("status")
-    private String status;
-
-    @JsonProperty("progress")
-    private String progress;
-
-    @JsonProperty("progressDetail")
-    private ProgressDetail progressDetail;
-
-    public String getStatus() {
-        return status;
-    }
-
-    public String getProgress() {
-        return progress;
-    }
-
-    public ProgressDetail getProgressDetail() {
-        return progressDetail;
-    }
-
-    @JsonIgnoreProperties(ignoreUnknown = true)
-    public static class ProgressDetail implements Serializable {
-        @JsonProperty("current")
-        int current;
-
-        @Override
-        public String toString() {
-            return "current " + current;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return Objects.toStringHelper(this).add("status", status).add("progress", progress)
-                .add("progressDetail", progressDetail).toString();
-    }
-}
diff --git a/src/main/java/com/github/dockerjava/api/model/PushResponseItem.java b/src/main/java/com/github/dockerjava/api/model/PushResponseItem.java
new file mode 100644
index 00000000..b9704215
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/api/model/PushResponseItem.java
@@ -0,0 +1,12 @@
+package com.github.dockerjava.api.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * Represents a push response stream item
+ */
+@JsonIgnoreProperties(ignoreUnknown = false)
+public class PushResponseItem extends ResponseItem {
+
+    private static final long serialVersionUID = 8256977108011295857L;
+}
diff --git a/src/main/java/com/github/dockerjava/api/model/ResponseItem.java b/src/main/java/com/github/dockerjava/api/model/ResponseItem.java
new file mode 100644
index 00000000..f7c4c502
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/api/model/ResponseItem.java
@@ -0,0 +1,89 @@
+package com.github.dockerjava.api.model;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Represents a pull response stream item
+ */
+@JsonIgnoreProperties(ignoreUnknown = false)
+public class ResponseItem implements Serializable {
+
+    private static final long serialVersionUID = -5187169652557467828L;
+
+    @JsonProperty("status")
+    private String status;
+
+    @JsonProperty("progress")
+    private String progress;
+
+    @JsonProperty("progressDetail")
+    private ProgressDetail progressDetail;
+
+    @JsonProperty("error")
+    private String error;
+
+    @JsonProperty("errorDetail")
+    private ErrorDetail errorDetail;
+
+    @JsonProperty("id")
+    private String id;
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getProgress() {
+        return progress;
+    }
+
+    public ProgressDetail getProgressDetail() {
+        return progressDetail;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = false)
+    public static class ProgressDetail implements Serializable {
+        private static final long serialVersionUID = -1954994695645715264L;
+
+        @JsonProperty("current")
+        int current;
+
+        @JsonProperty("total")
+        int total;
+
+        @Override
+        public String toString() {
+            return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
+        }
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = false)
+    public static class ErrorDetail implements Serializable {
+        private static final long serialVersionUID = -9136704865403084083L;
+
+        @JsonProperty("code")
+        String code;
+
+        @JsonProperty("message")
+        String message;
+
+        @Override
+        public String toString() {
+            return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
+    }
+}
diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java
index 81091039..947d42bf 100644
--- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java
+++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java
@@ -49,8 +49,11 @@ import com.github.dockerjava.api.command.WaitContainerCmd;
 import com.github.dockerjava.api.model.AuthConfig;
 import com.github.dockerjava.api.model.AuthConfigurations;
 import com.github.dockerjava.api.model.Event;
+import com.github.dockerjava.api.model.BuildResponseItem;
 import com.github.dockerjava.api.model.Frame;
 import com.github.dockerjava.api.model.Identifier;
+import com.github.dockerjava.api.model.PullResponseItem;
+import com.github.dockerjava.api.model.PushResponseItem;
 import com.github.dockerjava.api.model.Statistics;
 import com.github.dockerjava.core.command.AttachContainerCmdImpl;
 import com.github.dockerjava.core.command.AuthCmdImpl;
@@ -284,9 +287,8 @@ public class DockerClientImpl implements Closeable, DockerClient {
     }
 
     @Override
-    public AttachContainerCmd attachContainerCmd(String containerId, ResultCallback<Frame> resultCallback) {
-        return new AttachContainerCmdImpl(getDockerCmdExecFactory().createAttachContainerCmdExec(), containerId,
-                resultCallback);
+    public AttachContainerCmd attachContainerCmd(String containerId) {
+        return new AttachContainerCmdImpl(getDockerCmdExecFactory().createAttachContainerCmdExec(), containerId);
     }
 
     @Override
@@ -300,9 +302,8 @@ public class DockerClientImpl implements Closeable, DockerClient {
     }
 
     @Override
-    public LogContainerCmd logContainerCmd(String containerId, ResultCallback<Frame> resultCallback) {
-        return new LogContainerCmdImpl(getDockerCmdExecFactory().createLogContainerCmdExec(), containerId,
-                resultCallback);
+    public LogContainerCmd logContainerCmd(String containerId) {
+        return new LogContainerCmdImpl(getDockerCmdExecFactory().createLogContainerCmdExec(), containerId);
     }
 
     @Override
@@ -383,13 +384,13 @@ public class DockerClientImpl implements Closeable, DockerClient {
     }
 
     @Override
-    public EventsCmd eventsCmd(ResultCallback<Event> eventCallback) {
-        return new EventsCmdImpl(getDockerCmdExecFactory().createEventsCmdExec(), eventCallback);
+    public EventsCmd eventsCmd() {
+        return new EventsCmdImpl(getDockerCmdExecFactory().createEventsCmdExec());
     }
 
     @Override
-    public StatsCmd statsCmd(ResultCallback<Statistics> statisticsCallback) {
-        return new StatsCmdImpl(getDockerCmdExecFactory().createStatsCmdExec(), statisticsCallback);
+    public StatsCmd statsCmd() {
+        return new StatsCmdImpl(getDockerCmdExecFactory().createStatsCmdExec());
     }
 
     @Override
diff --git a/src/main/java/com/github/dockerjava/core/async/JsonStreamProcessor.java b/src/main/java/com/github/dockerjava/core/async/JsonStreamProcessor.java
index 5339b3ed..8c8cb8d3 100644
--- a/src/main/java/com/github/dockerjava/core/async/JsonStreamProcessor.java
+++ b/src/main/java/com/github/dockerjava/core/async/JsonStreamProcessor.java
@@ -7,6 +7,7 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonFactory.Feature;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -33,15 +34,22 @@ public class JsonStreamProcessor<T> implements ResponseStreamProcessor<T> {
     public void processResponseStream(InputStream response, ResultCallback<T> resultCallback) {
 
         resultCallback.onStart(response);
+        OBJECT_MAPPER.configure(com.fasterxml.jackson.core.JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
 
         try {
             JsonParser jp = JSON_FACTORY.createParser(response);
-            while (!jp.isClosed() && jp.nextToken() != JsonToken.END_OBJECT) {
+            boolean closed = jp.isClosed();
+            JsonToken nextToken = jp.nextToken();
+            while (!closed && nextToken != null && nextToken != JsonToken.END_OBJECT) {
                 try {
-                    resultCallback.onNext(OBJECT_MAPPER.readValue(jp, clazz));
+                    T next = OBJECT_MAPPER.readValue(jp, clazz);
+                    resultCallback.onNext(next);
                 } catch (Exception e) {
                     resultCallback.onError(e);
                 }
+
+                closed = jp.isClosed();
+                nextToken = jp.nextToken();
             }
         } catch (Throwable t) {
             resultCallback.onError(t);
diff --git a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java
index 50cc1fd9..a4e08e5a 100644
--- a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java
+++ b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java
@@ -16,7 +16,7 @@ import com.github.dockerjava.api.async.ResultCallback;
  * @author marcus
  *
  */
-public abstract class ResultCallbackTemplate<T> implements ResultCallback<T> {
+public abstract class ResultCallbackTemplate<RC_T extends ResultCallback<A_RES_T>, A_RES_T> implements ResultCallback<A_RES_T> {
 
     private final CountDownLatch finished = new CountDownLatch(1);
 
@@ -28,7 +28,7 @@ public abstract class ResultCallbackTemplate<T> implements ResultCallback<T> {
     }
 
     @Override
-    public void onNext(T object) {
+    public void onNext(A_RES_T object) {
     }
 
     @Override
@@ -60,11 +60,21 @@ public abstract class ResultCallbackTemplate<T> implements ResultCallback<T> {
         finished.countDown();
     }
 
-    public void awaitFinish() throws InterruptedException {
+    /**
+     * Blocks until {@link ResultCallback#onComplete()} was called
+     */
+    @SuppressWarnings("unchecked")
+    public RC_T awaitCompletion() throws InterruptedException {
         finished.await();
+        return (RC_T) this;
     }
 
-    public void awaitFinish(long timeout, TimeUnit timeUnit) throws InterruptedException {
+    /**
+     * Blocks until {@link ResultCallback#onComplete()} was called or the given timeout occurs
+     */
+    @SuppressWarnings("unchecked")
+    public RC_T awaitCompletion(long timeout, TimeUnit timeUnit) throws InterruptedException {
         finished.await(timeout, timeUnit);
+        return (RC_T) this;
     }
 }
diff --git a/src/main/java/com/github/dockerjava/core/command/AbstrAsyncDockerCmd.java b/src/main/java/com/github/dockerjava/core/command/AbstrAsyncDockerCmd.java
new file mode 100644
index 00000000..43293f3f
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/core/command/AbstrAsyncDockerCmd.java
@@ -0,0 +1,38 @@
+package com.github.dockerjava.core.command;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.command.AsyncDockerCmd;
+import com.github.dockerjava.api.command.DockerCmdAsyncExec;
+
+public abstract class AbstrAsyncDockerCmd<CMD_T extends AsyncDockerCmd<CMD_T, A_RES_T>, A_RES_T> implements
+        AsyncDockerCmd<CMD_T, A_RES_T> {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(AbstrAsyncDockerCmd.class);
+
+    protected DockerCmdAsyncExec<CMD_T, A_RES_T> execution;
+
+    public AbstrAsyncDockerCmd(DockerCmdAsyncExec<CMD_T, A_RES_T> execution) {
+        checkNotNull(execution, "execution was not specified");
+        this.execution = execution;
+    }
+
+    @Override
+    public <T extends ResultCallback<A_RES_T>> T exec(T resultCallback) {
+        execution.exec((CMD_T) this, resultCallback);
+        return resultCallback;
+    }
+
+    @Override
+    public void close() throws IOException {
+    }
+
+
+
+}
diff --git a/src/main/java/com/github/dockerjava/core/command/AbstrAuthCfgDockerCmd.java b/src/main/java/com/github/dockerjava/core/command/AbstrAuthCfgDockerCmd.java
index 7e9957cb..341b6a88 100644
--- a/src/main/java/com/github/dockerjava/core/command/AbstrAuthCfgDockerCmd.java
+++ b/src/main/java/com/github/dockerjava/core/command/AbstrAuthCfgDockerCmd.java
@@ -8,17 +8,17 @@ import org.apache.commons.codec.binary.Base64;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.github.dockerjava.api.command.DockerCmd;
-import com.github.dockerjava.api.command.DockerCmdExec;
+import com.github.dockerjava.api.command.DockerCmdSyncExec;
 import com.github.dockerjava.api.model.AuthConfig;
 
 public abstract class AbstrAuthCfgDockerCmd<T extends DockerCmd<RES_T>, RES_T> extends AbstrDockerCmd<T, RES_T> {
 
-    public AbstrAuthCfgDockerCmd(DockerCmdExec<T, RES_T> execution, AuthConfig authConfig) {
+    public AbstrAuthCfgDockerCmd(DockerCmdSyncExec<T, RES_T> execution, AuthConfig authConfig) {
         super(execution);
         withOptionalAuthConfig(authConfig);
     }
 
-    public AbstrAuthCfgDockerCmd(DockerCmdExec<T, RES_T> execution) {
+    public AbstrAuthCfgDockerCmd(DockerCmdSyncExec<T, RES_T> execution) {
         super(execution);
     }
 
@@ -39,12 +39,6 @@ public abstract class AbstrAuthCfgDockerCmd<T extends DockerCmd<RES_T>, RES_T> e
         return (T) this;
     }
 
-    protected String registryAuth() {
-        try {
-            return Base64.encodeBase64String(new ObjectMapper().writeValueAsString(authConfig).getBytes());
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
+
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/github/dockerjava/core/command/AbstrDockerCmd.java b/src/main/java/com/github/dockerjava/core/command/AbstrDockerCmd.java
index 069fba09..c4fedac5 100644
--- a/src/main/java/com/github/dockerjava/core/command/AbstrDockerCmd.java
+++ b/src/main/java/com/github/dockerjava/core/command/AbstrDockerCmd.java
@@ -4,20 +4,24 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
 
+import org.apache.commons.codec.binary.Base64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.github.dockerjava.api.DockerException;
 import com.github.dockerjava.api.command.DockerCmd;
-import com.github.dockerjava.api.command.DockerCmdExec;
+import com.github.dockerjava.api.command.DockerCmdSyncExec;
+import com.github.dockerjava.api.command.SyncDockerCmd;
+import com.github.dockerjava.api.model.AuthConfig;
 
-public abstract class AbstrDockerCmd<CMD_T extends DockerCmd<RES_T>, RES_T> implements DockerCmd<RES_T> {
+public abstract class AbstrDockerCmd<CMD_T extends DockerCmd<RES_T>, RES_T> implements SyncDockerCmd<RES_T> {
 
     private final static Logger LOGGER = LoggerFactory.getLogger(AbstrDockerCmd.class);
 
-    protected DockerCmdExec<CMD_T, RES_T> execution;
+    protected DockerCmdSyncExec<CMD_T, RES_T> execution;
 
-    public AbstrDockerCmd(DockerCmdExec<CMD_T, RES_T> execution) {
+    public AbstrDockerCmd(DockerCmdSyncExec<CMD_T, RES_T> execution) {
         checkNotNull(execution, "execution was not specified");
         this.execution = execution;
     }
@@ -32,4 +36,12 @@ public abstract class AbstrDockerCmd<CMD_T extends DockerCmd<RES_T>, RES_T> impl
     @Override
     public void close() throws IOException {
     }
+
+    protected String registryAuth(AuthConfig authConfig) {
+        try {
+            return Base64.encodeBase64String(new ObjectMapper().writeValueAsString(authConfig).getBytes());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/src/main/java/com/github/dockerjava/core/command/AttachContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/AttachContainerCmdImpl.java
index eabbb848..222ea9b3 100644
--- a/src/main/java/com/github/dockerjava/core/command/AttachContainerCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/AttachContainerCmdImpl.java
@@ -22,29 +22,15 @@ import com.github.dockerjava.api.model.Frame;
  * @param timestamps
  *            - true or false, if true, print timestamps for every log line. Defaults to false.
  */
-public class AttachContainerCmdImpl extends AbstrDockerCmd<AttachContainerCmd, Void> implements AttachContainerCmd {
-
-    private ResultCallback<Frame> resultCallback;
+public class AttachContainerCmdImpl extends AbstrAsyncDockerCmd<AttachContainerCmd, Frame> implements AttachContainerCmd {
 
     private String containerId;
 
     private boolean logs, followStream, timestamps, stdout, stderr;
 
-    public AttachContainerCmdImpl(AttachContainerCmd.Exec exec, String containerId, ResultCallback<Frame> resultCallback) {
+    public AttachContainerCmdImpl(AttachContainerCmd.Exec exec, String containerId) {
         super(exec);
         withContainerId(containerId);
-        withResultCallback(resultCallback);
-    }
-
-    public ResultCallback<Frame> getResultCallback() {
-        return resultCallback;
-    }
-
-    @Override
-    public AttachContainerCmd withResultCallback(ResultCallback<Frame> resultCallback) {
-        checkNotNull(resultCallback, "resultCallback was not specified");
-        this.resultCallback = resultCallback;
-        return this;
     }
 
     @Override
@@ -133,13 +119,4 @@ public class AttachContainerCmdImpl extends AbstrDockerCmd<AttachContainerCmd, V
     public AttachContainerCmd withLogs() {
         return withLogs(true);
     }
-
-    /**
-     * @throws NotFoundException
-     *             No such container
-     */
-    @Override
-    public Void exec() throws NotFoundException {
-        return super.exec();
-    }
 }
diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java
index f61d3b7a..56ce8f78 100644
--- a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java
@@ -8,15 +8,16 @@ import java.io.InputStream;
 
 import com.github.dockerjava.api.command.BuildImageCmd;
 import com.github.dockerjava.api.model.AuthConfigurations;
+import com.github.dockerjava.api.model.BuildResponseItem;
 import com.github.dockerjava.core.FilePathUtil;
 import com.github.dockerjava.core.dockerfile.Dockerfile;
 
 /**
- * 
+ *
  * Build an image from Dockerfile.
- * 
+ *
  */
-public class BuildImageCmdImpl extends AbstrDockerCmd<BuildImageCmd, BuildImageCmd.Response> implements BuildImageCmd {
+public class BuildImageCmdImpl extends AbstrAsyncDockerCmd<BuildImageCmd, BuildResponseItem> implements BuildImageCmd {
 
     private InputStream tarInputStream = null;
 
diff --git a/src/main/java/com/github/dockerjava/core/command/EventStreamReader.java b/src/main/java/com/github/dockerjava/core/command/EventStreamReader.java
deleted file mode 100644
index ffa71d6c..00000000
--- a/src/main/java/com/github/dockerjava/core/command/EventStreamReader.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.github.dockerjava.core.command;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class EventStreamReader<I> implements AutoCloseable {
-
-    private final ObjectMapper objectMapper = new ObjectMapper();
-
-    private final Class<I> type;
-
-    private final InputStream inputStream;
-
-    public EventStreamReader(InputStream inputStream, Class<I> type) {
-        this.inputStream = inputStream;
-        this.type = type;
-    }
-
-    public I readItem() throws IOException {
-        try {
-            return objectMapper.readValue(inputStream, type);
-        } catch (IOException e) {
-            // dirty, but works
-            if (e.getMessage().equals("Stream closed")) {
-                return null;
-            }
-            throw e;
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        inputStream.close();
-    }
-}
diff --git a/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java
index d1de2e60..f371c5b7 100644
--- a/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java
@@ -7,17 +7,14 @@ import com.github.dockerjava.api.model.Event;
 /**
  * Stream docker events
  */
-public class EventsCmdImpl extends AbstrDockerCmd<EventsCmd, Void> implements EventsCmd {
+public class EventsCmdImpl extends AbstrAsyncDockerCmd<EventsCmd, Event> implements EventsCmd {
 
     private String since;
 
     private String until;
 
-    private ResultCallback<Event> resultCallback;
-
-    public EventsCmdImpl(EventsCmd.Exec exec, ResultCallback<Event> resultCallback) {
+    public EventsCmdImpl(EventsCmd.Exec exec) {
         super(exec);
-        withResultCallback(resultCallback);
     }
 
     @Override
@@ -32,12 +29,6 @@ public class EventsCmdImpl extends AbstrDockerCmd<EventsCmd, Void> implements Ev
         return this;
     }
 
-    @Override
-    public EventsCmd withResultCallback(ResultCallback<Event> resultCallback) {
-        this.resultCallback = resultCallback;
-        return this;
-    }
-
     @Override
     public String getSince() {
         return since;
@@ -48,11 +39,6 @@ public class EventsCmdImpl extends AbstrDockerCmd<EventsCmd, Void> implements Ev
         return until;
     }
 
-    @Override
-    public ResultCallback<Event> getResultCallback() {
-        return resultCallback;
-    }
-
     @Override
     public String toString() {
         return new StringBuilder("events").append(since != null ? " --since=" + since : "")
diff --git a/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java
index 55fad8c9..ade3923f 100644
--- a/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java
@@ -1,7 +1,7 @@
 package com.github.dockerjava.core.command;
 
 import com.github.dockerjava.api.NotFoundException;
-import com.github.dockerjava.api.command.DockerCmdExec;
+import com.github.dockerjava.api.command.DockerCmdSyncExec;
 import com.github.dockerjava.api.command.InspectExecCmd;
 import com.github.dockerjava.api.command.InspectExecResponse;
 import com.google.common.base.Preconditions;
diff --git a/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java
index 9476ecc9..490b6b1a 100644
--- a/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/LogContainerCmdImpl.java
@@ -24,9 +24,7 @@ import com.github.dockerjava.api.model.Frame;
  * @param tail
  *            - `all` or `<number>`, Output specified number of lines at the end of logs
  */
-public class LogContainerCmdImpl extends AbstrDockerCmd<LogContainerCmd, Void> implements LogContainerCmd {
-
-    private ResultCallback<Frame> resultCallback;
+public class LogContainerCmdImpl extends AbstrAsyncDockerCmd<LogContainerCmd, Frame> implements LogContainerCmd {
 
     private String containerId;
 
@@ -34,10 +32,9 @@ public class LogContainerCmdImpl extends AbstrDockerCmd<LogContainerCmd, Void> i
 
     private boolean followStream, timestamps, stdout, stderr;
 
-    public LogContainerCmdImpl(LogContainerCmd.Exec exec, String containerId, ResultCallback<Frame> resultCallback) {
+    public LogContainerCmdImpl(LogContainerCmd.Exec exec, String containerId) {
         super(exec);
         withContainerId(containerId);
-        withResultCallback(resultCallback);
     }
 
     @Override
@@ -45,18 +42,6 @@ public class LogContainerCmdImpl extends AbstrDockerCmd<LogContainerCmd, Void> i
         return containerId;
     }
 
-    @Override
-    public ResultCallback<Frame> getResultCallback() {
-        return resultCallback;
-    }
-
-    @Override
-    public LogContainerCmd withResultCallback(ResultCallback<Frame> resultCallback) {
-        checkNotNull(resultCallback, "resultCallback was not specified");
-        this.resultCallback = resultCallback;
-        return this;
-    }
-
     @Override
     public int getTail() {
         return tail;
@@ -151,12 +136,4 @@ public class LogContainerCmdImpl extends AbstrDockerCmd<LogContainerCmd, Void> i
                 .append(timestamps ? "--timestamps=true" : "").append(containerId).toString();
     }
 
-    /**
-     * @throws NotFoundException
-     *             No such container
-     */
-    @Override
-    public Void exec() throws NotFoundException {
-        return super.exec();
-    }
 }
diff --git a/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java
index 488562b9..2fe46f12 100644
--- a/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java
@@ -2,25 +2,42 @@ package com.github.dockerjava.core.command;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import java.io.InputStream;
-
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.PullImageCmd;
 import com.github.dockerjava.api.model.AuthConfig;
+import com.github.dockerjava.api.model.PullResponseItem;
 
 /**
  *
  * Pull image from repository.
  *
  */
-public class PullImageCmdImpl extends AbstrAuthCfgDockerCmd<PullImageCmd, InputStream> implements PullImageCmd {
+public class PullImageCmdImpl extends AbstrAsyncDockerCmd<PullImageCmd, PullResponseItem> implements PullImageCmd {
 
     private String repository, tag, registry;
 
+    private AuthConfig authConfig;
+
     public PullImageCmdImpl(PullImageCmd.Exec exec, AuthConfig authConfig, String repository) {
-        super(exec, authConfig);
+        super(exec);
+        withOptionalAuthConfig(authConfig);
         withRepository(repository);
     }
 
+    public AuthConfig getAuthConfig() {
+        return authConfig;
+    }
+
+    public PullImageCmd withAuthConfig(AuthConfig authConfig) {
+        checkNotNull(authConfig, "authConfig was not specified");
+        return withOptionalAuthConfig(authConfig);
+    }
+
+    private PullImageCmd withOptionalAuthConfig(AuthConfig authConfig) {
+        this.authConfig = authConfig;
+        return this;
+    }
+
     @Override
     public String getRepository() {
         return repository;
diff --git a/src/main/java/com/github/dockerjava/core/command/PushImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/PushImageCmdImpl.java
index 76bbe46b..81f1262f 100644
--- a/src/main/java/com/github/dockerjava/core/command/PushImageCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/PushImageCmdImpl.java
@@ -2,8 +2,9 @@ package com.github.dockerjava.core.command;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.api.command.PushImageCmd;
+import com.github.dockerjava.api.model.AuthConfig;
+import com.github.dockerjava.api.model.PushResponseItem;
 
 /**
  * Push the latest image to the repository.
@@ -11,13 +12,14 @@ import com.github.dockerjava.api.command.PushImageCmd;
  * @param name
  *            The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
  */
-public class PushImageCmdImpl extends AbstrAuthCfgDockerCmd<PushImageCmd, PushImageCmd.Response> implements
-        PushImageCmd {
+public class PushImageCmdImpl extends AbstrAsyncDockerCmd<PushImageCmd, PushResponseItem> implements PushImageCmd {
 
     private String name;
 
     private String tag;
 
+    private AuthConfig authConfig;
+
     public PushImageCmdImpl(PushImageCmd.Exec exec, String name) {
         super(exec);
         withName(name);
@@ -55,17 +57,24 @@ public class PushImageCmdImpl extends AbstrAuthCfgDockerCmd<PushImageCmd, PushIm
         return this;
     }
 
+    public AuthConfig getAuthConfig() {
+        return authConfig;
+    }
+
+    public PushImageCmd withAuthConfig(AuthConfig authConfig) {
+        checkNotNull(authConfig, "authConfig was not specified");
+        return withOptionalAuthConfig(authConfig);
+    }
+
+    private PushImageCmd withOptionalAuthConfig(AuthConfig authConfig) {
+        this.authConfig = authConfig;
+        return this;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder("push ").append(name).toString();
     }
 
-    /**
-     * @throws NotFoundException
-     *             No such image
-     */
-    @Override
-    public Response exec() throws NotFoundException {
-        return super.exec();
-    }
+
 }
diff --git a/src/main/java/com/github/dockerjava/core/command/StatsCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/StatsCmdImpl.java
index 678a9ef4..205f619b 100644
--- a/src/main/java/com/github/dockerjava/core/command/StatsCmdImpl.java
+++ b/src/main/java/com/github/dockerjava/core/command/StatsCmdImpl.java
@@ -9,15 +9,12 @@ import com.github.dockerjava.api.model.Statistics;
 /**
  * Container stats
  */
-public class StatsCmdImpl extends AbstrDockerCmd<StatsCmd, Void> implements StatsCmd {
+public class StatsCmdImpl extends AbstrAsyncDockerCmd<StatsCmd, Statistics> implements StatsCmd {
 
     private String containerId;
 
-    private ResultCallback<Statistics> resultCallback;
-
-    public StatsCmdImpl(StatsCmd.Exec exec, ResultCallback<Statistics> resultCallback) {
+    public StatsCmdImpl(StatsCmd.Exec exec) {
         super(exec);
-        withResultCallback(resultCallback);
     }
 
     @Override
@@ -32,22 +29,6 @@ public class StatsCmdImpl extends AbstrDockerCmd<StatsCmd, Void> implements Stat
         return containerId;
     }
 
-    @Override
-    public StatsCmd withResultCallback(ResultCallback<Statistics> resultCallback) {
-        this.resultCallback = resultCallback;
-        return this;
-    }
-
-    @Override
-    public ResultCallback<Statistics> getResultCallback() {
-        return resultCallback;
-    }
-
-    @Override
-    public Void exec() {
-        return super.exec();
-    }
-
     @Override
     public String toString() {
         return new StringBuilder("stats").append(containerId != null ? " --id=" + containerId : "").toString();
diff --git a/src/main/java/com/github/dockerjava/jaxrs/AbstrAsyncDockerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/AbstrAsyncDockerCmdExec.java
new file mode 100644
index 00000000..cb91a56e
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/jaxrs/AbstrAsyncDockerCmdExec.java
@@ -0,0 +1,71 @@
+package com.github.dockerjava.jaxrs;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import javax.ws.rs.client.WebTarget;
+
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.command.AsyncDockerCmd;
+import com.github.dockerjava.api.command.DockerCmdAsyncExec;
+import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
+
+public abstract class AbstrAsyncDockerCmdExec<CMD_T extends AsyncDockerCmd<CMD_T, A_RES_T>, A_RES_T> extends
+        AbstrDockerCmdExec implements DockerCmdAsyncExec<CMD_T, A_RES_T> {
+
+    public AbstrAsyncDockerCmdExec(WebTarget baseResource) {
+        super(baseResource);
+    }
+
+    @Override
+    public Void exec(CMD_T command, ResultCallback<A_RES_T> resultCallback) {
+        return execute(command, resultCallback);
+    }
+
+    protected final Void execute(final CMD_T command, final ResultCallback<A_RES_T> resultCallback) {
+
+        ResultCallback<A_RES_T> delegatingResultCallback = new ResultCallback<A_RES_T>() {
+
+            @Override
+            public void close() throws IOException {
+                resultCallback.close();
+                command.close();
+            }
+
+            @Override
+            public void onStart(Closeable closeable) {
+                resultCallback.onStart(closeable);
+            }
+
+            @Override
+            public void onNext(A_RES_T object) {
+                resultCallback.onNext(object);
+            }
+
+            @Override
+            public void onError(Throwable throwable) {
+                resultCallback.onError(throwable);
+            }
+
+            @Override
+            public void onComplete() {
+                resultCallback.onComplete();
+                try {
+                    command.close();
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+
+        AbstractCallbackNotifier<A_RES_T> callbackNotifier = callbackNotifier(command, delegatingResultCallback);
+
+        AbstractCallbackNotifier.startAsyncProcessing(callbackNotifier);
+
+        return null;
+    }
+
+    protected abstract AbstractCallbackNotifier<A_RES_T> callbackNotifier(CMD_T command,
+            ResultCallback<A_RES_T> resultCallback);
+
+}
diff --git a/src/main/java/com/github/dockerjava/jaxrs/AbstrDockerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/AbstrDockerCmdExec.java
index 7ce68eed..beca08c1 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/AbstrDockerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/AbstrDockerCmdExec.java
@@ -4,19 +4,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
 
-import javax.ws.rs.ProcessingException;
 import javax.ws.rs.client.WebTarget;
 
 import org.apache.commons.codec.binary.Base64;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.github.dockerjava.api.DockerException;
-import com.github.dockerjava.api.command.DockerCmd;
-import com.github.dockerjava.api.command.DockerCmdExec;
 import com.github.dockerjava.api.model.AuthConfig;
 import com.github.dockerjava.api.model.AuthConfigurations;
 
-public abstract class AbstrDockerCmdExec<CMD_T extends DockerCmd<RES_T>, RES_T> implements DockerCmdExec<CMD_T, RES_T> {
+public abstract class AbstrDockerCmdExec {
 
     private WebTarget baseResource;
 
@@ -45,29 +41,5 @@ public abstract class AbstrDockerCmdExec<CMD_T extends DockerCmd<RES_T>, RES_T>
         }
     }
 
-    @Override
-    public RES_T exec(CMD_T command) {
-        // this hack works because of ResponseStatusExceptionFilter
-        RES_T result;
-        try {
-            result = execute(command);
-
-        } catch (ProcessingException e) {
-            if (e.getCause() instanceof DockerException) {
-                throw (DockerException) e.getCause();
-            } else {
-                throw e;
-            }
-        } finally {
-            try {
-                command.close();
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        return result;
-    }
 
-    protected abstract RES_T execute(CMD_T command);
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/AbstrSyncDockerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/AbstrSyncDockerCmdExec.java
new file mode 100644
index 00000000..7e26c519
--- /dev/null
+++ b/src/main/java/com/github/dockerjava/jaxrs/AbstrSyncDockerCmdExec.java
@@ -0,0 +1,44 @@
+package com.github.dockerjava.jaxrs;
+
+import java.io.IOException;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.WebTarget;
+
+import com.github.dockerjava.api.DockerException;
+import com.github.dockerjava.api.command.DockerCmd;
+import com.github.dockerjava.api.command.DockerCmdSyncExec;
+
+public abstract class AbstrSyncDockerCmdExec<CMD_T extends DockerCmd<RES_T>, RES_T> extends AbstrDockerCmdExec
+        implements DockerCmdSyncExec<CMD_T, RES_T> {
+
+    public AbstrSyncDockerCmdExec(WebTarget baseResource) {
+        super(baseResource);
+    }
+
+    @Override
+    public RES_T exec(CMD_T command) {
+        // this hack works because of ResponseStatusExceptionFilter
+        RES_T result;
+        try {
+            result = execute(command);
+
+        } catch (ProcessingException e) {
+            if (e.getCause() instanceof DockerException) {
+                throw (DockerException) e.getCause();
+            } else {
+                throw e;
+            }
+        } finally {
+            try {
+                command.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        return result;
+    }
+
+    protected abstract RES_T execute(CMD_T command);
+}
diff --git a/src/main/java/com/github/dockerjava/jaxrs/AttachContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/AttachContainerCmdExec.java
index edf837d7..36b904dd 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/AttachContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/AttachContainerCmdExec.java
@@ -5,13 +5,14 @@ import javax.ws.rs.client.WebTarget;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.AttachContainerCmd;
 import com.github.dockerjava.api.model.Frame;
 import com.github.dockerjava.core.async.FrameStreamProcessor;
 import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
 import com.github.dockerjava.jaxrs.async.POSTCallbackNotifier;
 
-public class AttachContainerCmdExec extends AbstrDockerCmdExec<AttachContainerCmd, Void> implements
+public class AttachContainerCmdExec extends AbstrAsyncDockerCmdExec<AttachContainerCmd, Frame> implements
         AttachContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(AttachContainerCmdExec.class);
@@ -21,7 +22,9 @@ public class AttachContainerCmdExec extends AbstrDockerCmdExec<AttachContainerCm
     }
 
     @Override
-    protected Void execute(AttachContainerCmd command) {
+    protected AbstractCallbackNotifier<Frame> callbackNotifier(AttachContainerCmd command,
+            ResultCallback<Frame> resultCallback) {
+
         WebTarget webTarget = getBaseResource().path("/containers/{id}/attach")
                 .resolveTemplate("id", command.getContainerId())
                 .queryParam("logs", command.hasLogsEnabled() ? "1" : "0")
@@ -32,11 +35,7 @@ public class AttachContainerCmdExec extends AbstrDockerCmdExec<AttachContainerCm
 
         LOGGER.trace("POST: {}", webTarget);
 
-        POSTCallbackNotifier<Frame> callbackNotifier = new POSTCallbackNotifier<Frame>(new FrameStreamProcessor(),
-                command.getResultCallback(), webTarget);
-
-        AbstractCallbackNotifier.startAsyncProcessing(callbackNotifier);
-
-        return null;
+        return new POSTCallbackNotifier<Frame>(new FrameStreamProcessor(),
+                resultCallback, webTarget.request(), null);
     }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java
index 8ceca593..9dfe9d11 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java
@@ -12,7 +12,7 @@ import javax.ws.rs.core.Response;
 
 import static javax.ws.rs.client.Entity.entity;
 
-public class AuthCmdExec extends AbstrDockerCmdExec<AuthCmd, AuthResponse> implements AuthCmd.Exec {
+public class AuthCmdExec extends AbstrSyncDockerCmdExec<AuthCmd, AuthResponse> implements AuthCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(AuthCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java
index 3380832e..00d907a4 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java
@@ -1,28 +1,25 @@
 package com.github.dockerjava.jaxrs;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
-import com.github.dockerjava.api.command.BuildImageCmd;
-import com.github.dockerjava.api.model.AuthConfigurations;
-import com.github.dockerjava.api.model.EventStreamItem;
-import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream;
-import com.google.common.collect.ImmutableList;
-import org.glassfish.jersey.client.ClientProperties;
-import org.glassfish.jersey.client.RequestEntityProcessing;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import static javax.ws.rs.client.Entity.entity;
 
 import javax.ws.rs.client.Invocation;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Iterator;
 
-import static javax.ws.rs.client.Entity.entity;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class BuildImageCmdExec extends AbstrDockerCmdExec<BuildImageCmd, BuildImageCmd.Response> implements
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.command.BuildImageCmd;
+import com.github.dockerjava.api.model.AuthConfigurations;
+import com.github.dockerjava.api.model.BuildResponseItem;
+import com.github.dockerjava.core.async.JsonStreamProcessor;
+import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
+import com.github.dockerjava.jaxrs.async.POSTCallbackNotifier;
+
+public class BuildImageCmdExec extends AbstrAsyncDockerCmdExec<BuildImageCmd, BuildResponseItem> implements
         BuildImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(BuildImageCmdExec.class);
@@ -31,81 +28,48 @@ public class BuildImageCmdExec extends AbstrDockerCmdExec<BuildImageCmd, BuildIm
         super(baseResource);
     }
 
+    private Invocation.Builder resourceWithOptionalAuthConfig(BuildImageCmd command, Invocation.Builder request) {
+        AuthConfigurations authConfigs = command.getBuildAuthConfigs();
+        if (authConfigs != null) {
+            request = request.header("X-Registry-Config", registryConfigs(authConfigs));
+        }
+        return request;
+    }
+
     @Override
-    protected ResponseImpl execute(BuildImageCmd command) {
-        WebTarget webResource = getBaseResource().path("/build");
+    protected AbstractCallbackNotifier<BuildResponseItem> callbackNotifier(BuildImageCmd command,
+            ResultCallback<BuildResponseItem> resultCallback) {
+
+        WebTarget webTarget = getBaseResource().path("/build");
         String dockerFilePath = command.getPathToDockerfile();
 
         if (command.getTag() != null) {
-            webResource = webResource.queryParam("t", command.getTag());
+            webTarget = webTarget.queryParam("t", command.getTag());
         }
         if (command.hasNoCacheEnabled()) {
-            webResource = webResource.queryParam("nocache", "true");
+            webTarget = webTarget.queryParam("nocache", "true");
         }
         if (!command.hasRemoveEnabled()) {
-            webResource = webResource.queryParam("rm", "false");
+            webTarget = webTarget.queryParam("rm", "false");
         }
         if (command.isQuiet()) {
-            webResource = webResource.queryParam("q", "true");
+            webTarget = webTarget.queryParam("q", "true");
         }
         if (command.hasPullEnabled()) {
-            webResource = webResource.queryParam("pull", "true");
+            webTarget = webTarget.queryParam("pull", "true");
         }
         if (dockerFilePath != null && !"Dockerfile".equals(dockerFilePath)) {
-            webResource = webResource.queryParam("dockerfile", dockerFilePath);
-        }
-
-        webResource.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
-        webResource.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024 * 1024);
-
-        LOGGER.debug("POST: {}", webResource);
-        Response response = resourceWithOptionalAuthConfig(command, webResource.request()).accept(MediaType.TEXT_PLAIN)
-                .post(entity(command.getTarInputStream(), "application/tar"), Response.class);
-
-        return new ResponseImpl(new WrappedResponseInputStream(response));
-
-    }
-
-    private Invocation.Builder resourceWithOptionalAuthConfig(BuildImageCmd command, Invocation.Builder request) {
-        AuthConfigurations authConfigs = command.getBuildAuthConfigs();
-        if (authConfigs != null) {
-            request = request.header("X-Registry-Config", registryConfigs(authConfigs));
+            webTarget = webTarget.queryParam("dockerfile", dockerFilePath);
         }
-        return request;
-    }
 
-    public static class ResponseImpl extends BuildImageCmd.Response {
-
-        private final InputStream proxy;
-
-        public ResponseImpl(InputStream proxy) {
-            this.proxy = proxy;
-        }
+        webTarget.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
+        webTarget.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024 * 1024);
 
-        @Override
-        public Iterable<EventStreamItem> getItems() throws IOException {
-            ObjectMapper mapper = new ObjectMapper();
-            // we'll be reading instances of MyBean
-            ObjectReader reader = mapper.reader(EventStreamItem.class);
-            // and then do other configuration, if any, and read:
-            Iterator<EventStreamItem> items = reader.readValues(proxy);
+        LOGGER.trace("POST: {}", webTarget);
 
-            try {
-                return ImmutableList.copyOf(items);
-            } finally {
-                proxy.close();
-            }
-        }
-
-        @Override
-        public int read() throws IOException {
-            return proxy.read();
-        }
-
-        @Override
-        public void close() throws IOException {
-            proxy.close();
-            super.close();
-        }
+        return new POSTCallbackNotifier<BuildResponseItem>(
+                new JsonStreamProcessor<BuildResponseItem>(BuildResponseItem.class), resultCallback,
+                resourceWithOptionalAuthConfig(command, webTarget.request()).accept(MediaType.TEXT_PLAIN), entity(
+                        command.getTarInputStream(), "application/tar"));
     }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/CommitCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CommitCmdExec.java
index b07f5e33..fec4da6a 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/CommitCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/CommitCmdExec.java
@@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.github.dockerjava.api.command.CommitCmd;
 
-public class CommitCmdExec extends AbstrDockerCmdExec<CommitCmd, String> implements CommitCmd.Exec {
+public class CommitCmdExec extends AbstrSyncDockerCmdExec<CommitCmd, String> implements CommitCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(CommitCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java
index c7c8c293..aa7878a6 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/ContainerDiffCmdExec.java
@@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.ContainerDiffCmd;
 import com.github.dockerjava.api.model.ChangeLog;
 
-public class ContainerDiffCmdExec extends AbstrDockerCmdExec<ContainerDiffCmd, List<ChangeLog>> implements
+public class ContainerDiffCmdExec extends AbstrSyncDockerCmdExec<ContainerDiffCmd, List<ChangeLog>> implements
         ContainerDiffCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ContainerDiffCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java
index 88e8c308..ec6d0b76 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/CopyFileFromContainerCmdExec.java
@@ -14,7 +14,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.CopyFileFromContainerCmd;
 import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream;
 
-public class CopyFileFromContainerCmdExec extends AbstrDockerCmdExec<CopyFileFromContainerCmd, InputStream> implements
+public class CopyFileFromContainerCmdExec extends AbstrSyncDockerCmdExec<CopyFileFromContainerCmd, InputStream> implements
         CopyFileFromContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(CopyFileFromContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/CreateContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CreateContainerCmdExec.java
index c02b9f4b..265057c0 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/CreateContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/CreateContainerCmdExec.java
@@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.CreateContainerCmd;
 import com.github.dockerjava.api.command.CreateContainerResponse;
 
-public class CreateContainerCmdExec extends AbstrDockerCmdExec<CreateContainerCmd, CreateContainerResponse> implements
+public class CreateContainerCmdExec extends AbstrSyncDockerCmdExec<CreateContainerCmd, CreateContainerResponse> implements
         CreateContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(CreateContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/CreateImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/CreateImageCmdExec.java
index c5733241..baba3982 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/CreateImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/CreateImageCmdExec.java
@@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.CreateImageCmd;
 import com.github.dockerjava.api.command.CreateImageResponse;
 
-public class CreateImageCmdExec extends AbstrDockerCmdExec<CreateImageCmd, CreateImageResponse> implements
+public class CreateImageCmdExec extends AbstrSyncDockerCmdExec<CreateImageCmd, CreateImageResponse> implements
         CreateImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(CreateImageCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java
index e6f27ae6..1bd38048 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/EventsCmdExec.java
@@ -5,13 +5,14 @@ import javax.ws.rs.client.WebTarget;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.EventsCmd;
 import com.github.dockerjava.api.model.Event;
 import com.github.dockerjava.core.async.JsonStreamProcessor;
 import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
 import com.github.dockerjava.jaxrs.async.GETCallbackNotifier;
 
-public class EventsCmdExec extends AbstrDockerCmdExec<EventsCmd, Void> implements EventsCmd.Exec {
+public class EventsCmdExec extends AbstrAsyncDockerCmdExec<EventsCmd, Event> implements EventsCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(EventsCmdExec.class);
 
@@ -20,18 +21,13 @@ public class EventsCmdExec extends AbstrDockerCmdExec<EventsCmd, Void> implement
     }
 
     @Override
-    protected Void execute(EventsCmd command) {
-
+    protected AbstractCallbackNotifier<Event> callbackNotifier(EventsCmd command, ResultCallback<Event> resultCallback) {
         WebTarget webTarget = getBaseResource().path("/events").queryParam("since", command.getSince())
                 .queryParam("until", command.getUntil());
 
         LOGGER.trace("GET: {}", webTarget);
 
-        GETCallbackNotifier<Event> callbackNotifier = new GETCallbackNotifier<Event>(new JsonStreamProcessor<Event>(
-                Event.class), command.getResultCallback(), webTarget);
-
-        AbstractCallbackNotifier.startAsyncProcessing(callbackNotifier);
-
-        return null;
+        return new GETCallbackNotifier<Event>(new JsonStreamProcessor<Event>(
+                Event.class), resultCallback, webTarget.request());
     }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/ExecCreateCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ExecCreateCmdExec.java
index e2d986bb..573d8947 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/ExecCreateCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/ExecCreateCmdExec.java
@@ -10,7 +10,7 @@ import javax.ws.rs.core.MediaType;
 
 import static javax.ws.rs.client.Entity.entity;
 
-public class ExecCreateCmdExec extends AbstrDockerCmdExec<ExecCreateCmd, ExecCreateCmdResponse> implements
+public class ExecCreateCmdExec extends AbstrSyncDockerCmdExec<ExecCreateCmd, ExecCreateCmdResponse> implements
         ExecCreateCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(VersionCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/ExecStartCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ExecStartCmdExec.java
index 46d0e2d2..58c19e55 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/ExecStartCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/ExecStartCmdExec.java
@@ -14,7 +14,7 @@ import java.io.InputStream;
 
 import static javax.ws.rs.client.Entity.entity;
 
-public class ExecStartCmdExec extends AbstrDockerCmdExec<ExecStartCmd, InputStream> implements ExecStartCmd.Exec {
+public class ExecStartCmdExec extends AbstrSyncDockerCmdExec<ExecStartCmd, InputStream> implements ExecStartCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ExecStartCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/InfoCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/InfoCmdExec.java
index eafb87b9..141d7d1d 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/InfoCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/InfoCmdExec.java
@@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.InfoCmd;
 import com.github.dockerjava.api.model.Info;
 
-public class InfoCmdExec extends AbstrDockerCmdExec<InfoCmd, Info> implements InfoCmd.Exec {
+public class InfoCmdExec extends AbstrSyncDockerCmdExec<InfoCmd, Info> implements InfoCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(InfoCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/InspectContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/InspectContainerCmdExec.java
index a06e46e7..9c6e34a9 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/InspectContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/InspectContainerCmdExec.java
@@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.InspectContainerCmd;
 import com.github.dockerjava.api.command.InspectContainerResponse;
 
-public class InspectContainerCmdExec extends AbstrDockerCmdExec<InspectContainerCmd, InspectContainerResponse>
+public class InspectContainerCmdExec extends AbstrSyncDockerCmdExec<InspectContainerCmd, InspectContainerResponse>
         implements InspectContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(InspectContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java
index a58a520c..0a99acc0 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 
-public class InspectExecCmdExec extends AbstrDockerCmdExec<InspectExecCmd, InspectExecResponse> implements
+public class InspectExecCmdExec extends AbstrSyncDockerCmdExec<InspectExecCmd, InspectExecResponse> implements
         InspectExecCmd.Exec {
     private static final Logger LOGGER = LoggerFactory.getLogger(InspectExecCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/InspectImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/InspectImageCmdExec.java
index b03cdd79..9148887e 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/InspectImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/InspectImageCmdExec.java
@@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.InspectImageCmd;
 import com.github.dockerjava.api.command.InspectImageResponse;
 
-public class InspectImageCmdExec extends AbstrDockerCmdExec<InspectImageCmd, InspectImageResponse> implements
+public class InspectImageCmdExec extends AbstrSyncDockerCmdExec<InspectImageCmd, InspectImageResponse> implements
         InspectImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(InspectImageCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/KillContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/KillContainerCmdExec.java
index bbfd0dbe..9b132dee 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/KillContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/KillContainerCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.KillContainerCmd;
 
-public class KillContainerCmdExec extends AbstrDockerCmdExec<KillContainerCmd, Void> implements KillContainerCmd.Exec {
+public class KillContainerCmdExec extends AbstrSyncDockerCmdExec<KillContainerCmd, Void> implements KillContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(KillContainerCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java
index 5feb5bda..ddd5d321 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java
@@ -14,7 +14,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.ListContainersCmd;
 import com.github.dockerjava.api.model.Container;
 
-public class ListContainersCmdExec extends AbstrDockerCmdExec<ListContainersCmd, List<Container>> implements
+public class ListContainersCmdExec extends AbstrSyncDockerCmdExec<ListContainersCmd, List<Container>> implements
         ListContainersCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ListContainersCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/ListImagesCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ListImagesCmdExec.java
index b18470e1..df88cf1d 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/ListImagesCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/ListImagesCmdExec.java
@@ -14,7 +14,7 @@ import com.github.dockerjava.api.model.Image;
 
 import static com.google.common.net.UrlEscapers.urlPathSegmentEscaper;
 
-public class ListImagesCmdExec extends AbstrDockerCmdExec<ListImagesCmd, List<Image>> implements ListImagesCmd.Exec {
+public class ListImagesCmdExec extends AbstrSyncDockerCmdExec<ListImagesCmd, List<Image>> implements ListImagesCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ListImagesCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java
index d6e62cd7..0ab3da7a 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/LogContainerCmdExec.java
@@ -5,13 +5,15 @@ import javax.ws.rs.client.WebTarget;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.LogContainerCmd;
 import com.github.dockerjava.api.model.Frame;
 import com.github.dockerjava.core.async.FrameStreamProcessor;
 import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
 import com.github.dockerjava.jaxrs.async.GETCallbackNotifier;
 
-public class LogContainerCmdExec extends AbstrDockerCmdExec<LogContainerCmd, Void> implements LogContainerCmd.Exec {
+public class LogContainerCmdExec extends AbstrAsyncDockerCmdExec<LogContainerCmd, Frame> implements
+        LogContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(LogContainerCmdExec.class);
 
@@ -20,7 +22,9 @@ public class LogContainerCmdExec extends AbstrDockerCmdExec<LogContainerCmd, Voi
     }
 
     @Override
-    protected Void execute(LogContainerCmd command) {
+    protected AbstractCallbackNotifier<Frame> callbackNotifier(LogContainerCmd command,
+            ResultCallback<Frame> resultCallback) {
+
         WebTarget webTarget = getBaseResource().path("/containers/{id}/logs")
                 .resolveTemplate("id", command.getContainerId())
                 .queryParam("timestamps", command.hasTimestampsEnabled() ? "1" : "0")
@@ -31,11 +35,6 @@ public class LogContainerCmdExec extends AbstrDockerCmdExec<LogContainerCmd, Voi
 
         LOGGER.trace("GET: {}", webTarget);
 
-        GETCallbackNotifier<Frame> callbackNotifier = new GETCallbackNotifier<Frame>(new FrameStreamProcessor(),
-                command.getResultCallback(), webTarget);
-
-        AbstractCallbackNotifier.startAsyncProcessing(callbackNotifier);
-
-        return null;
+        return new GETCallbackNotifier<Frame>(new FrameStreamProcessor(), resultCallback, webTarget.request());
     }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/PauseContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/PauseContainerCmdExec.java
index 4bd8ddd9..04bb68a6 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/PauseContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/PauseContainerCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.PauseContainerCmd;
 
-public class PauseContainerCmdExec extends AbstrDockerCmdExec<PauseContainerCmd, Void> implements
+public class PauseContainerCmdExec extends AbstrSyncDockerCmdExec<PauseContainerCmd, Void> implements
         PauseContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(PauseContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/PingCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/PingCmdExec.java
index 9e2677e5..875155c9 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/PingCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/PingCmdExec.java
@@ -7,7 +7,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.PingCmd;
 
-public class PingCmdExec extends AbstrDockerCmdExec<PingCmd, Void> implements PingCmd.Exec {
+public class PingCmdExec extends AbstrSyncDockerCmdExec<PingCmd, Void> implements PingCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(PingCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java
index c317aa1c..dfba3c1c 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java
@@ -1,20 +1,25 @@
 package com.github.dockerjava.jaxrs;
 
-import java.io.InputStream;
+import static javax.ws.rs.client.Entity.entity;
 
 import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.PullImageCmd;
 import com.github.dockerjava.api.model.AuthConfig;
-import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream;
+import com.github.dockerjava.api.model.PullResponseItem;
+import com.github.dockerjava.core.async.JsonStreamProcessor;
+import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
+import com.github.dockerjava.jaxrs.async.POSTCallbackNotifier;
 
-public class PullImageCmdExec extends AbstrDockerCmdExec<PullImageCmd, InputStream> implements PullImageCmd.Exec {
+public class PullImageCmdExec extends AbstrAsyncDockerCmdExec<PullImageCmd, PullResponseItem> implements
+        PullImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(PullImageCmdExec.class);
 
@@ -22,18 +27,6 @@ public class PullImageCmdExec extends AbstrDockerCmdExec<PullImageCmd, InputStre
         super(baseResource);
     }
 
-    @Override
-    protected InputStream execute(PullImageCmd command) {
-        WebTarget webResource = getBaseResource().path("/images/create").queryParam("tag", command.getTag())
-                .queryParam("fromImage", command.getRepository()).queryParam("registry", command.getRegistry());
-
-        LOGGER.trace("POST: {}", webResource);
-        Response response = resourceWithOptionalAuthConfig(command, webResource.request()).accept(
-                MediaType.APPLICATION_OCTET_STREAM_TYPE).post(null);
-
-        return new WrappedResponseInputStream(response);
-    }
-
     private Invocation.Builder resourceWithOptionalAuthConfig(PullImageCmd command, Invocation.Builder request) {
         AuthConfig authConfig = command.getAuthConfig();
         if (authConfig != null) {
@@ -42,4 +35,18 @@ public class PullImageCmdExec extends AbstrDockerCmdExec<PullImageCmd, InputStre
         return request;
     }
 
+    @Override
+    protected AbstractCallbackNotifier<PullResponseItem> callbackNotifier(PullImageCmd command,
+            ResultCallback<PullResponseItem> resultCallback) {
+
+        WebTarget webResource = getBaseResource().path("/images/create").queryParam("tag", command.getTag())
+                .queryParam("fromImage", command.getRepository()).queryParam("registry", command.getRegistry());
+
+        LOGGER.trace("POST: {}", webResource);
+        Builder builder = resourceWithOptionalAuthConfig(command, webResource.request()).accept(
+                MediaType.APPLICATION_OCTET_STREAM_TYPE);
+
+        return new POSTCallbackNotifier<PullResponseItem>(new JsonStreamProcessor<PullResponseItem>(
+                PullResponseItem.class), resultCallback, builder, entity(null, MediaType.APPLICATION_JSON));
+    }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/PushImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/PushImageCmdExec.java
index 4f5ca5d0..8e79fc66 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/PushImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/PushImageCmdExec.java
@@ -2,28 +2,23 @@ package com.github.dockerjava.jaxrs;
 
 import static javax.ws.rs.client.Entity.entity;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Iterator;
-
+import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.PushImageCmd;
-import com.github.dockerjava.api.command.PushImageCmd.Response;
 import com.github.dockerjava.api.model.AuthConfig;
-import com.github.dockerjava.api.model.PushEventStreamItem;
-
-import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream;
-// Shaded, but imported
-import com.google.common.collect.ImmutableList;
+import com.github.dockerjava.api.model.PushResponseItem;
+import com.github.dockerjava.core.async.JsonStreamProcessor;
+import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
+import com.github.dockerjava.jaxrs.async.POSTCallbackNotifier;
 
-public class PushImageCmdExec extends AbstrDockerCmdExec<PushImageCmd, Response> implements PushImageCmd.Exec {
+public class PushImageCmdExec extends AbstrAsyncDockerCmdExec<PushImageCmd, PushResponseItem> implements
+        PushImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(PushImageCmdExec.class);
 
@@ -31,51 +26,26 @@ public class PushImageCmdExec extends AbstrDockerCmdExec<PushImageCmd, Response>
         super(baseResource);
     }
 
-    @Override
-    protected ResponseImpl execute(PushImageCmd command) {
-        WebTarget webResource = getBaseResource().path("/images/" + name(command) + "/push").queryParam("tag",
-                command.getTag());
-
-        final String registryAuth = registryAuth(command.getAuthConfig());
-        LOGGER.trace("POST: {}", webResource);
-        javax.ws.rs.core.Response response = webResource.request().header("X-Registry-Auth", registryAuth)
-                .accept(MediaType.APPLICATION_JSON).post(entity(Response.class, MediaType.APPLICATION_JSON));
-
-        return new ResponseImpl(new WrappedResponseInputStream(response));
-    }
-
     private String name(PushImageCmd command) {
         String name = command.getName();
         AuthConfig authConfig = command.getAuthConfig();
         return name.contains("/") ? name : authConfig.getUsername();
     }
 
-    public static class ResponseImpl extends Response {
-
-        private final InputStream proxy;
+    @Override
+    protected AbstractCallbackNotifier<PushResponseItem> callbackNotifier(PushImageCmd command,
+            ResultCallback<PushResponseItem> resultCallback) {
 
-        ResponseImpl(InputStream proxy) {
-            this.proxy = proxy;
-        }
+        WebTarget webResource = getBaseResource().path("/images/" + name(command) + "/push").queryParam("tag",
+                command.getTag());
 
-        @Override
-        public Iterable<PushEventStreamItem> getItems() throws IOException {
-            ObjectMapper mapper = new ObjectMapper();
-            // we'll be reading instances of MyBean
-            ObjectReader reader = mapper.reader(PushEventStreamItem.class);
-            // and then do other configuration, if any, and read:
-            Iterator<PushEventStreamItem> items = reader.readValues(proxy);
+        final String registryAuth = registryAuth(command.getAuthConfig());
+        LOGGER.trace("POST: {}", webResource);
 
-            try {
-                return ImmutableList.copyOf(items);
-            } finally {
-                proxy.close();
-            }
-        }
+        Builder builder = webResource.request().header("X-Registry-Auth", registryAuth)
+                .accept(MediaType.APPLICATION_JSON);
 
-        @Override
-        public int read() throws IOException {
-            return proxy.read();
-        }
+        return new POSTCallbackNotifier<PushResponseItem>(new JsonStreamProcessor<PushResponseItem>(
+                PushResponseItem.class), resultCallback, builder, entity(null, MediaType.APPLICATION_JSON));
     }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java
index ebd98fc6..2e72c37b 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/RemoveContainerCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.RemoveContainerCmd;
 
-public class RemoveContainerCmdExec extends AbstrDockerCmdExec<RemoveContainerCmd, Void> implements
+public class RemoveContainerCmdExec extends AbstrSyncDockerCmdExec<RemoveContainerCmd, Void> implements
         RemoveContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(RemoveContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java
index 8db23112..18d477c5 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/RemoveImageCmdExec.java
@@ -7,7 +7,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.RemoveImageCmd;
 
-public class RemoveImageCmdExec extends AbstrDockerCmdExec<RemoveImageCmd, Void> implements RemoveImageCmd.Exec {
+public class RemoveImageCmdExec extends AbstrSyncDockerCmdExec<RemoveImageCmd, Void> implements RemoveImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(RemoveImageCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/RestartContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/RestartContainerCmdExec.java
index f640945a..0a4fced8 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/RestartContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/RestartContainerCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.RestartContainerCmd;
 
-public class RestartContainerCmdExec extends AbstrDockerCmdExec<RestartContainerCmd, Void> implements
+public class RestartContainerCmdExec extends AbstrSyncDockerCmdExec<RestartContainerCmd, Void> implements
         RestartContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(RestartContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/SaveImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/SaveImageCmdExec.java
index de56a39b..39a06f15 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/SaveImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/SaveImageCmdExec.java
@@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.SaveImageCmd;
 import com.github.dockerjava.jaxrs.util.WrappedResponseInputStream;
 
-public class SaveImageCmdExec extends AbstrDockerCmdExec<SaveImageCmd, InputStream> implements SaveImageCmd.Exec {
+public class SaveImageCmdExec extends AbstrSyncDockerCmdExec<SaveImageCmd, InputStream> implements SaveImageCmd.Exec {
     private static final Logger LOGGER = LoggerFactory.getLogger(SaveImageCmdExec.class);
 
     public SaveImageCmdExec(WebTarget baseResource) {
diff --git a/src/main/java/com/github/dockerjava/jaxrs/SearchImagesCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/SearchImagesCmdExec.java
index 00aeb91e..1de9943d 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/SearchImagesCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/SearchImagesCmdExec.java
@@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.SearchImagesCmd;
 import com.github.dockerjava.api.model.SearchItem;
 
-public class SearchImagesCmdExec extends AbstrDockerCmdExec<SearchImagesCmd, List<SearchItem>> implements
+public class SearchImagesCmdExec extends AbstrSyncDockerCmdExec<SearchImagesCmd, List<SearchItem>> implements
         SearchImagesCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(SearchImagesCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java
index c90f5e1c..8b41f2cd 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/StartContainerCmdExec.java
@@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.StartContainerCmd;
 
-public class StartContainerCmdExec extends AbstrDockerCmdExec<StartContainerCmd, Void> implements
+public class StartContainerCmdExec extends AbstrSyncDockerCmdExec<StartContainerCmd, Void> implements
         StartContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(StartContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/StatsCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/StatsCmdExec.java
index 683ecca4..10fbd1ca 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/StatsCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/StatsCmdExec.java
@@ -5,13 +5,14 @@ import javax.ws.rs.client.WebTarget;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.StatsCmd;
 import com.github.dockerjava.api.model.Statistics;
 import com.github.dockerjava.core.async.JsonStreamProcessor;
 import com.github.dockerjava.jaxrs.async.AbstractCallbackNotifier;
 import com.github.dockerjava.jaxrs.async.GETCallbackNotifier;
 
-public class StatsCmdExec extends AbstrDockerCmdExec<StatsCmd, Void> implements StatsCmd.Exec {
+public class StatsCmdExec extends AbstrAsyncDockerCmdExec<StatsCmd, Statistics> implements StatsCmd.Exec {
     private static final Logger LOGGER = LoggerFactory.getLogger(StatsCmdExec.class);
 
     public StatsCmdExec(WebTarget baseResource) {
@@ -19,17 +20,15 @@ public class StatsCmdExec extends AbstrDockerCmdExec<StatsCmd, Void> implements
     }
 
     @Override
-    protected Void execute(StatsCmd command) {
+    protected AbstractCallbackNotifier<Statistics> callbackNotifier(StatsCmd command,
+            ResultCallback<Statistics> resultCallback) {
+
         WebTarget webTarget = getBaseResource().path("/containers/{id}/stats").resolveTemplate("id",
                 command.getContainerId());
 
         LOGGER.trace("GET: {}", webTarget);
 
-        GETCallbackNotifier<Statistics> callbackNotifier = new GETCallbackNotifier<Statistics>(
-                new JsonStreamProcessor<Statistics>(Statistics.class), command.getResultCallback(), webTarget);
-
-        AbstractCallbackNotifier.startAsyncProcessing(callbackNotifier);
-
-        return null;
+        return new GETCallbackNotifier<Statistics>(new JsonStreamProcessor<Statistics>(Statistics.class),
+                resultCallback, webTarget.request());
     }
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/StopContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/StopContainerCmdExec.java
index 3197e0c0..d881ce1c 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/StopContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/StopContainerCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.StopContainerCmd;
 
-public class StopContainerCmdExec extends AbstrDockerCmdExec<StopContainerCmd, Void> implements StopContainerCmd.Exec {
+public class StopContainerCmdExec extends AbstrSyncDockerCmdExec<StopContainerCmd, Void> implements StopContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(StopContainerCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/TagImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/TagImageCmdExec.java
index 3cddd63f..f697b22b 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/TagImageCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/TagImageCmdExec.java
@@ -7,7 +7,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.TagImageCmd;
 
-public class TagImageCmdExec extends AbstrDockerCmdExec<TagImageCmd, Void> implements TagImageCmd.Exec {
+public class TagImageCmdExec extends AbstrSyncDockerCmdExec<TagImageCmd, Void> implements TagImageCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(TagImageCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/TopContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/TopContainerCmdExec.java
index daff2224..092e9548 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/TopContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/TopContainerCmdExec.java
@@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.TopContainerCmd;
 import com.github.dockerjava.api.command.TopContainerResponse;
 
-public class TopContainerCmdExec extends AbstrDockerCmdExec<TopContainerCmd, TopContainerResponse> implements
+public class TopContainerCmdExec extends AbstrSyncDockerCmdExec<TopContainerCmd, TopContainerResponse> implements
         TopContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(TopContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/UnpauseContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/UnpauseContainerCmdExec.java
index de507e8f..3005f663 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/UnpauseContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/UnpauseContainerCmdExec.java
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
 
 import com.github.dockerjava.api.command.UnpauseContainerCmd;
 
-public class UnpauseContainerCmdExec extends AbstrDockerCmdExec<UnpauseContainerCmd, Void> implements
+public class UnpauseContainerCmdExec extends AbstrSyncDockerCmdExec<UnpauseContainerCmd, Void> implements
         UnpauseContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(UnpauseContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/VersionCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/VersionCmdExec.java
index e8af1cb2..0c1611bc 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/VersionCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/VersionCmdExec.java
@@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
 import com.github.dockerjava.api.command.VersionCmd;
 import com.github.dockerjava.api.model.Version;
 
-public class VersionCmdExec extends AbstrDockerCmdExec<VersionCmd, Version> implements VersionCmd.Exec {
+public class VersionCmdExec extends AbstrSyncDockerCmdExec<VersionCmd, Version> implements VersionCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(VersionCmdExec.class);
 
diff --git a/src/main/java/com/github/dockerjava/jaxrs/WaitContainerCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/WaitContainerCmdExec.java
index 47af2bcf..a916e1b5 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/WaitContainerCmdExec.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/WaitContainerCmdExec.java
@@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.github.dockerjava.api.command.WaitContainerCmd;
 
-public class WaitContainerCmdExec extends AbstrDockerCmdExec<WaitContainerCmd, Integer> implements
+public class WaitContainerCmdExec extends AbstrSyncDockerCmdExec<WaitContainerCmd, Integer> implements
         WaitContainerCmd.Exec {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(WaitContainerCmdExec.class);
diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java
index 6cfc7a76..3076b136 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java
@@ -12,7 +12,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
 import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.core.Response;
 
 import com.github.dockerjava.api.async.ResultCallback;
@@ -25,15 +25,15 @@ public abstract class AbstractCallbackNotifier<T> implements Callable<Void> {
 
     private final ResultCallback<T> resultCallback;
 
-    protected final WebTarget webTarget;
+    protected final Builder requestBuilder;
 
     protected AbstractCallbackNotifier(ResponseStreamProcessor<T> responseStreamProcessor,
-            ResultCallback<T> resultCallback, WebTarget webTarget) {
-        checkNotNull(webTarget, "An WebTarget must be provided");
+            ResultCallback<T> resultCallback, Builder requestBuilder) {
+        checkNotNull(requestBuilder, "An WebTarget must be provided");
         checkNotNull(responseStreamProcessor, "A ResponseStreamProcessor must be provided");
         this.responseStreamProcessor = responseStreamProcessor;
         this.resultCallback = resultCallback;
-        this.webTarget = webTarget;
+        this.requestBuilder = requestBuilder;
     }
 
     @Override
diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/GETCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/GETCallbackNotifier.java
index cddfe49e..99669647 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/async/GETCallbackNotifier.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/async/GETCallbackNotifier.java
@@ -3,14 +3,13 @@
  */
 package com.github.dockerjava.jaxrs.async;
 
-import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.core.Response;
 
 import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.core.async.ResponseStreamProcessor;
 
 /**
- * <TODO: class description>
  *
  * @author marcus
  *
@@ -18,12 +17,12 @@ import com.github.dockerjava.core.async.ResponseStreamProcessor;
 public class GETCallbackNotifier<T> extends AbstractCallbackNotifier<T> {
 
     public GETCallbackNotifier(ResponseStreamProcessor<T> responseStreamProcessor, ResultCallback<T> resultCallback,
-            WebTarget webTarget) {
-        super(responseStreamProcessor, resultCallback, webTarget);
+            Builder requestBuilder) {
+        super(responseStreamProcessor, resultCallback, requestBuilder);
     }
 
     protected Response response() {
-        return webTarget.request().get(Response.class);
+        return requestBuilder.get(Response.class);
     }
 
 }
diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/POSTCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/POSTCallbackNotifier.java
index 0d380b5d..9fe84895 100644
--- a/src/main/java/com/github/dockerjava/jaxrs/async/POSTCallbackNotifier.java
+++ b/src/main/java/com/github/dockerjava/jaxrs/async/POSTCallbackNotifier.java
@@ -3,27 +3,30 @@
  */
 package com.github.dockerjava.jaxrs.async;
 
-import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.core.Response;
 
 import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.core.async.ResponseStreamProcessor;
 
 /**
- * <TODO: class description>
  *
  * @author marcus
  *
  */
 public class POSTCallbackNotifier<T> extends AbstractCallbackNotifier<T> {
 
+    Entity<?> entity = null;
+
     public POSTCallbackNotifier(ResponseStreamProcessor<T> responseStreamProcessor, ResultCallback<T> resultCallback,
-            WebTarget webTarget) {
-        super(responseStreamProcessor, resultCallback, webTarget);
+            Builder requestBuilder, Entity<?> entity) {
+        super(responseStreamProcessor, resultCallback, requestBuilder);
+        this.entity = entity;
     }
 
     protected Response response() {
-        return webTarget.request().post(null, Response.class);
+        return requestBuilder.post(entity, Response.class);
     }
 
 }


Test patch:
diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java
index 7faca037..d492c415 100644
--- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java
+++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java
@@ -2,11 +2,15 @@ package com.github.dockerjava.client;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
 
 import com.github.dockerjava.api.DockerClient;
 import com.github.dockerjava.api.DockerException;
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.InspectContainerResponse;
+import com.github.dockerjava.api.model.BuildResponseItem;
 import com.github.dockerjava.api.model.Frame;
+import com.github.dockerjava.api.model.PullResponseItem;
 import com.github.dockerjava.api.model.Volume;
 import com.github.dockerjava.api.model.VolumeBind;
 import com.github.dockerjava.core.DockerClientBuilder;
@@ -17,11 +21,13 @@ import com.google.common.base.Joiner;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.LineIterator;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.ITestResult;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringWriter;
@@ -40,15 +46,16 @@ public abstract class AbstractDockerClientTest extends Assert {
     protected TestDockerCmdExecFactory dockerCmdExecFactory = new TestDockerCmdExecFactory(
             DockerClientBuilder.getDefaultDockerCmdExecFactory());
 
-    public void beforeTest() {
+    public void beforeTest() throws Exception {
 
         LOG.info("======================= BEFORETEST =======================");
         LOG.info("Connecting to Docker server");
         dockerClient = DockerClientBuilder.getInstance(config()).withDockerCmdExecFactory(dockerCmdExecFactory).build();
 
         LOG.info("Pulling image 'busybox'");
+
         // need to block until image is pulled completely
-        asString(dockerClient.pullImageCmd("busybox").withTag("latest").exec());
+        dockerClient.pullImageCmd("busybox").withTag("latest").exec(new PullResponseCallback()).awaitCompletion();
 
         assertNotNull(dockerClient);
         LOG.info("======================= END OF BEFORETEST =======================\n\n");
@@ -181,10 +188,30 @@ public abstract class AbstractDockerClientTest extends Assert {
         assertThat(volumes, contains(expectedVolumes));
     }
 
-    public static class CollectFramesCallback extends ResultCallbackTemplate<Frame> {
-        public final List<Frame> frames = new ArrayList<Frame>();
+    public static class CollectFramesCallback extends CollectStreamItemCallback<CollectFramesCallback, Frame> {
+
+        @Override
+        public void onNext(Frame frame) {
+            items.add(frame);
+            log.append(new String(frame.getPayload()));
+        }
+
+    }
+
+    protected String containerLog(String containerId) throws Exception {
+
+        CollectFramesCallback collectFramesCallback = dockerClient.logContainerCmd(containerId).withStdOut()
+                .exec(new CollectFramesCallback());
 
-        private final StringBuffer log = new StringBuffer();
+        collectFramesCallback.awaitCompletion();
+
+        return collectFramesCallback.toString();
+    }
+
+    public static class CollectStreamItemCallback<RC_T extends ResultCallback<A_RES_T>, A_RES_T> extends ResultCallbackTemplate<RC_T, A_RES_T> {
+        public final List<A_RES_T> items = new ArrayList<A_RES_T>();
+
+        protected final StringBuffer log = new StringBuffer();
 
         @Override
         public void onError(Throwable throwable) {
@@ -193,9 +220,10 @@ public abstract class AbstractDockerClientTest extends Assert {
         }
 
         @Override
-        public void onNext(Frame frame) {
-            frames.add(frame);
-            log.append(new String(frame.getPayload()));
+        public void onNext(A_RES_T item) {
+            items.add(item);
+            log.append("" + item);
+            LOG.info(item.toString());
         }
 
         @Override
@@ -204,14 +232,21 @@ public abstract class AbstractDockerClientTest extends Assert {
         }
     }
 
-    protected String containerLog(String containerId) throws Exception {
+    public static class BuildLogCallback extends CollectStreamItemCallback<BuildLogCallback, BuildResponseItem> {
+        public String awaitImageId() throws Exception {
+            awaitCompletion();
+            BuildResponseItem item = items.get(items.size() - 1);
+            assertThat(item.toString(), containsString("Successfully built"));
+            return item.getStream().replaceFirst("Successfully built", "").trim();
+        }
+    }
 
-        CollectFramesCallback collectFramesCallback = new CollectFramesCallback();
+    public static class PullResponseCallback extends CollectStreamItemCallback<PullResponseCallback, PullResponseItem> {
 
-        dockerClient.logContainerCmd(containerId, collectFramesCallback).withStdOut().exec();
+    }
 
-        collectFramesCallback.awaitFinish();
+    protected String buildImage(File baseDir) throws Exception {
 
-        return collectFramesCallback.toString();
+        return dockerClient.buildImageCmd(baseDir).withNoCache().exec(new BuildLogCallback()).awaitImageId();
     }
 }
diff --git a/src/test/java/com/github/dockerjava/client/DockerClientTest.java b/src/test/java/com/github/dockerjava/client/DockerClientTest.java
index 85ee0d7a..120f4e82 100644
--- a/src/test/java/com/github/dockerjava/client/DockerClientTest.java
+++ b/src/test/java/com/github/dockerjava/client/DockerClientTest.java
@@ -27,7 +27,7 @@ public class DockerClientTest extends AbstractDockerClientTest {
     public static final Logger LOG = LoggerFactory.getLogger(DockerClientTest.class);
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java
index 380f5dd9..fdc58208 100644
--- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java
+++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java
@@ -1,21 +1,58 @@
 package com.github.dockerjava.core;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.github.dockerjava.api.command.*;
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.command.AttachContainerCmd;
 import com.github.dockerjava.api.command.AuthCmd.Exec;
-import com.github.dockerjava.jaxrs.BuildImageCmdExec;
+import com.github.dockerjava.api.command.BuildImageCmd;
+import com.github.dockerjava.api.command.CommitCmd;
+import com.github.dockerjava.api.command.ContainerDiffCmd;
+import com.github.dockerjava.api.command.CopyFileFromContainerCmd;
+import com.github.dockerjava.api.command.CreateContainerCmd;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.command.CreateImageCmd;
+import com.github.dockerjava.api.command.CreateImageResponse;
+import com.github.dockerjava.api.command.DockerCmdExecFactory;
+import com.github.dockerjava.api.command.EventsCmd;
+import com.github.dockerjava.api.command.ExecCreateCmd;
+import com.github.dockerjava.api.command.ExecStartCmd;
+import com.github.dockerjava.api.command.InfoCmd;
+import com.github.dockerjava.api.command.InspectContainerCmd;
+import com.github.dockerjava.api.command.InspectExecCmd;
+import com.github.dockerjava.api.command.InspectImageCmd;
+import com.github.dockerjava.api.command.KillContainerCmd;
+import com.github.dockerjava.api.command.ListContainersCmd;
+import com.github.dockerjava.api.command.ListImagesCmd;
+import com.github.dockerjava.api.command.LogContainerCmd;
+import com.github.dockerjava.api.command.PauseContainerCmd;
+import com.github.dockerjava.api.command.PingCmd;
+import com.github.dockerjava.api.command.PullImageCmd;
+import com.github.dockerjava.api.command.PushImageCmd;
+import com.github.dockerjava.api.command.RemoveContainerCmd;
+import com.github.dockerjava.api.command.RemoveImageCmd;
+import com.github.dockerjava.api.command.RestartContainerCmd;
+import com.github.dockerjava.api.command.SaveImageCmd;
+import com.github.dockerjava.api.command.SearchImagesCmd;
+import com.github.dockerjava.api.command.StartContainerCmd;
+import com.github.dockerjava.api.command.StatsCmd;
+import com.github.dockerjava.api.command.StopContainerCmd;
+import com.github.dockerjava.api.command.TagImageCmd;
+import com.github.dockerjava.api.command.TopContainerCmd;
+import com.github.dockerjava.api.command.UnpauseContainerCmd;
+import com.github.dockerjava.api.command.VersionCmd;
+import com.github.dockerjava.api.command.WaitContainerCmd;
+import com.github.dockerjava.api.model.BuildResponseItem;
 
 /**
  * Special {@link DockerCmdExecFactory} implementation that collects container and image creations while test execution
  * for the purpose of automatically cleanup.
- * 
+ *
  * @author marcus
- * 
+ *
  */
 public class TestDockerCmdExecFactory implements DockerCmdExecFactory {
 
@@ -91,16 +128,16 @@ public class TestDockerCmdExecFactory implements DockerCmdExecFactory {
     public BuildImageCmd.Exec createBuildImageCmdExec() {
         return new BuildImageCmd.Exec() {
             @Override
-            public BuildImageCmd.Response exec(BuildImageCmd command) {
+            public Void exec(BuildImageCmd command, ResultCallback<BuildResponseItem> resultCallback) {
                 // can't detect image id here so tagging it
                 String tag = command.getTag();
                 if (tag == null || "".equals(tag.trim())) {
                     tag = "" + new SecureRandom().nextInt(Integer.MAX_VALUE);
                     command.withTag(tag);
                 }
-                InputStream inputStream = delegate.createBuildImageCmdExec().exec(command);
+                delegate.createBuildImageCmdExec().exec(command, resultCallback);
                 imageNames.add(tag);
-                return new BuildImageCmdExec.ResponseImpl(inputStream);
+                return null;
             }
         };
     }
diff --git a/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java
index 9c5c5c69..cb9fb794 100644
--- a/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/AttachContainerCmdImplTest.java
@@ -6,12 +6,9 @@ import static org.hamcrest.Matchers.isEmptyString;
 import static org.hamcrest.Matchers.not;
 
 import java.io.File;
-import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.commons.io.HexDump;
-import org.apache.commons.lang.StringUtils;
 import org.testng.ITestResult;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.AfterTest;
@@ -19,7 +16,6 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-import com.github.dockerjava.api.DockerException;
 import com.github.dockerjava.api.command.CreateContainerResponse;
 import com.github.dockerjava.api.model.Frame;
 import com.github.dockerjava.api.model.StreamType;
@@ -29,7 +25,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class AttachContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -69,10 +65,10 @@ public class AttachContainerCmdImplTest extends AbstractDockerClientTest {
             };
         };
 
-        dockerClient.attachContainerCmd(container.getId(), collectFramesCallback).withStdErr().withStdOut()
-                .withFollowStream().withLogs().exec();
+        dockerClient.attachContainerCmd(container.getId()).withStdErr().withStdOut()
+                .withFollowStream().withLogs().exec(collectFramesCallback);
 
-        collectFramesCallback.awaitFinish(30, TimeUnit.SECONDS);
+        collectFramesCallback.awaitCompletion(30, TimeUnit.SECONDS);
 
         collectFramesCallback.close();
 
@@ -85,12 +81,7 @@ public class AttachContainerCmdImplTest extends AbstractDockerClientTest {
         File baseDir = new File(Thread.currentThread().getContextClassLoader()
                 .getResource("attachContainerTestDockerfile").getFile());
 
-        InputStream response = dockerClient.buildImageCmd(baseDir).withNoCache().exec();
-
-        String fullLog = asString(response);
-        assertThat(fullLog, containsString("Successfully built"));
-
-        String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim();
+        String imageId = buildImage(baseDir);
 
         CreateContainerResponse container = dockerClient.createContainerCmd(imageId).withTty(true).exec();
 
@@ -107,16 +98,16 @@ public class AttachContainerCmdImplTest extends AbstractDockerClientTest {
             };
         };
 
-        dockerClient.attachContainerCmd(container.getId(), collectFramesCallback).withStdErr().withStdOut()
-                .withFollowStream().exec();
+        dockerClient.attachContainerCmd(container.getId()).withStdErr().withStdOut()
+                .withFollowStream().exec(collectFramesCallback);
 
-        collectFramesCallback.awaitFinish(10, TimeUnit.SECONDS);
+        collectFramesCallback.awaitCompletion(15, TimeUnit.SECONDS);
 
         collectFramesCallback.close();
 
         System.out.println("log: " + collectFramesCallback.toString());
 
-        HexDump.dump(collectFramesCallback.toString().getBytes(), 0, System.out, 0);
+        //HexDump.dump(collectFramesCallback.toString().getBytes(), 0, System.out, 0);
 
         assertThat(collectFramesCallback.toString(), containsString("stdout\r\nstderr"));
     }
diff --git a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java
index 180d835b..36211b20 100644
--- a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java
@@ -1,20 +1,24 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
+import java.lang.reflect.Method;
+
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
 import com.github.dockerjava.api.UnauthorizedException;
 import com.github.dockerjava.api.model.AuthResponse;
 import com.github.dockerjava.client.AbstractDockerClientTest;
 import com.github.dockerjava.core.DockerClientBuilder;
-import org.testng.ITestResult;
-import org.testng.annotations.*;
-
-import java.lang.reflect.Method;
 
 @Test(groups = "integration")
 public class AuthCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java
index f90250ea..51dfd37a 100644
--- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java
@@ -27,12 +27,11 @@ import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
 import com.github.dockerjava.api.DockerClientException;
-import com.github.dockerjava.api.DockerException;
 import com.github.dockerjava.api.command.BuildImageCmd;
 import com.github.dockerjava.api.command.CreateContainerResponse;
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import com.github.dockerjava.api.command.InspectImageResponse;
-import com.github.dockerjava.api.model.EventStreamItem;
+import com.github.dockerjava.api.model.BuildResponseItem;
 import com.github.dockerjava.client.AbstractDockerClientTest;
 import com.github.dockerjava.core.CompressArchiveUtil;
 
@@ -40,7 +39,7 @@ import com.github.dockerjava.core.CompressArchiveUtil;
 public class BuildImageCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -60,15 +59,10 @@ public class BuildImageCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test
-    public void testNginxDockerfileBuilder() {
+    public void testNginxDockerfileBuilder() throws Exception {
         File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile());
 
-        InputStream response = dockerClient.buildImageCmd(baseDir).withNoCache().exec();
-
-        String fullLog = asString(response);
-        assertThat(fullLog, containsString("Successfully built"));
-
-        String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim();
+        String imageId = buildImage(baseDir);
 
         InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
         assertThat(inspectImageResponse, not(nullValue()));
@@ -78,27 +72,21 @@ public class BuildImageCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test(groups = "ignoreInCircleCi")
-    public void testNonstandard1() {
+    public void testNonstandard1() throws Exception {
         File baseDir = new File(Thread.currentThread().getContextClassLoader()
                 .getResource("nonstandard/subdirectory/Dockerfile-nonstandard").getFile());
 
-        InputStream response = dockerClient.buildImageCmd(baseDir).withNoCache().exec();
-
-        String fullLog = asString(response);
-        assertThat(fullLog, containsString("Successfully built"));
+        buildImage(baseDir);
     }
 
     @Test(groups = "ignoreInCircleCi")
-    public void testNonstandard2() {
+    public void testNonstandard2() throws Exception {
         File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nonstandard").getFile());
         File dockerFile = new File(Thread.currentThread().getContextClassLoader()
                 .getResource("nonstandard/subdirectory/Dockerfile-nonstandard").getFile());
 
-        InputStream response = dockerClient.buildImageCmd().withBaseDirectory(baseDir).withDockerfile(dockerFile)
-                .withNoCache().exec();
-
-        String fullLog = asString(response);
-        assertThat(fullLog, containsString("Successfully built"));
+        dockerClient.buildImageCmd().withBaseDirectory(baseDir).withDockerfile(dockerFile)
+                .withNoCache().exec(new BuildLogCallback()).awaitImageId();
     }
 
     @Test
@@ -149,21 +137,22 @@ public class BuildImageCmdImplTest extends AbstractDockerClientTest {
     }
 
     private String dockerfileBuild(InputStream tarInputStream) throws Exception {
+
         return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream));
     }
 
     private String dockerfileBuild(File baseDir) throws Exception {
+
         return execBuild(dockerClient.buildImageCmd(baseDir));
     }
 
     private String execBuild(BuildImageCmd buildImageCmd) throws Exception {
-        // Build image
-        InputStream response = buildImageCmd.withNoCache().exec();
 
-        String fullLog = asString(response);
-        assertThat(fullLog, containsString("Successfully built"));
+        BuildLogCallback resultCallback = new BuildLogCallback();;
+
+        buildImageCmd.withNoCache().exec(resultCallback);
 
-        String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim();
+        String imageId = resultCallback.awaitImageId();
 
         // Create container based on image
         CreateContainerResponse container = dockerClient.createContainerCmd(imageId).exec();
@@ -179,17 +168,19 @@ public class BuildImageCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test(expectedExceptions = { DockerClientException.class })
-    public void testDockerfileIgnored() {
+    public void testDockerfileIgnored() throws Exception{
         File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerfileIgnored")
                 .getFile());
-        dockerClient.buildImageCmd(baseDir).withNoCache().exec();
+
+        dockerClient.buildImageCmd(baseDir).withNoCache().exec(new BuildLogCallback()).awaitImageId();
     }
 
     @Test(expectedExceptions = { DockerClientException.class })
-    public void testInvalidDockerIgnorePattern() {
+    public void testInvalidDockerIgnorePattern() throws Exception {
         File baseDir = new File(Thread.currentThread().getContextClassLoader()
                 .getResource("testInvalidDockerignorePattern").getFile());
-        dockerClient.buildImageCmd(baseDir).withNoCache().exec();
+
+        dockerClient.buildImageCmd(baseDir).withNoCache().exec( new BuildLogCallback()).awaitImageId();
     }
 
     @Test(groups = "ignoreInCircleCi")
@@ -204,11 +195,14 @@ public class BuildImageCmdImplTest extends AbstractDockerClientTest {
     public void testNetCatDockerfileBuilder() throws InterruptedException, IOException {
         File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile());
 
-        Iterable<EventStreamItem> response = dockerClient.buildImageCmd(baseDir).withNoCache().exec().getItems();
+        BuildLogCallback resultCallback = new BuildLogCallback();
+        dockerClient.buildImageCmd(baseDir).withNoCache().exec(resultCallback);
+
+        resultCallback.awaitCompletion();
 
         String imageId = null;
 
-        for (EventStreamItem item : response) {
+        for (BuildResponseItem item : resultCallback.items) {
             String text = item.getStream();
             if (text.startsWith("Successfully built ")) {
                 imageId = StringUtils.substringBetween(text, "Successfully built ", "\n").trim();
diff --git a/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java
index 415ca8f0..657edf8d 100644
--- a/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/CommitCmdImplTest.java
@@ -26,7 +26,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class CommitCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java
index e94c8c6c..3db2b728 100644
--- a/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/ContainerDiffCmdImplTest.java
@@ -27,7 +27,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class ContainerDiffCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java
index 72a97d04..4f53bb77 100644
--- a/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/CopyFileFromContainerCmdImplTest.java
@@ -17,7 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 public class CopyFileFromContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java
index 9876e43d..d35efb63 100644
--- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java
@@ -26,7 +26,7 @@ import static org.hamcrest.Matchers.*;
 public class CreateContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/DockerfileFixture.java b/src/test/java/com/github/dockerjava/core/command/DockerfileFixture.java
index 2d6ec952..74ed3dae 100644
--- a/src/test/java/com/github/dockerjava/core/command/DockerfileFixture.java
+++ b/src/test/java/com/github/dockerjava/core/command/DockerfileFixture.java
@@ -8,6 +8,7 @@ import com.github.dockerjava.api.InternalServerErrorException;
 import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.api.model.Image;
 import com.github.dockerjava.client.AbstractDockerClientTest;
+import com.github.dockerjava.client.AbstractDockerClientTest.BuildLogCallback;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,18 +37,12 @@ public class DockerfileFixture implements AutoCloseable {
         this.directory = directory;
     }
 
-    public void open() throws IOException {
+    public void open() throws Exception {
 
         LOGGER.info("building {}", directory);
-        InputStream response = dockerClient.buildImageCmd(new File("src/test/resources", directory)).withNoCache() // remove
-                                                                                                                   // alternatives,
-                                                                                                                   // cause
-                                                                                                                   // problems
-                .exec();
 
-        String log = AbstractDockerClientTest.consumeAsString(response);
-
-        assertThat(log, containsString("Successfully built"));
+        dockerClient.buildImageCmd(new File("src/test/resources", directory)).withNoCache()
+                .exec(new BuildLogCallback()).awaitImageId();
 
         Image lastCreatedImage = dockerClient.listImagesCmd().exec().get(0);
 
diff --git a/src/test/java/com/github/dockerjava/core/command/EventStreamReaderITest.java b/src/test/java/com/github/dockerjava/core/command/EventStreamReaderITest.java
deleted file mode 100644
index c311540b..00000000
--- a/src/test/java/com/github/dockerjava/core/command/EventStreamReaderITest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.github.dockerjava.core.command;
-
-import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.model.EventStreamItem;
-import com.github.dockerjava.api.model.PullEventStreamItem;
-import com.github.dockerjava.core.DockerClientBuilder;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import java.io.File;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
-import static org.hamcrest.core.AllOf.allOf;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.testng.AssertJUnit.assertNull;
-
-@Test(groups = "integration")
-public class EventStreamReaderITest {
-
-    private DockerClient dockerClient;
-
-    @BeforeTest
-    public void setUp() throws Exception {
-        dockerClient = DockerClientBuilder.getInstance().build();
-    }
-
-    @AfterTest
-    public void tearDown() throws Exception {
-        dockerClient.close();
-    }
-
-    @Test(groups = "ignoreInCircleCi")
-    public void pullCanBeStreamed() throws Exception {
-
-        try (EventStreamReader<PullEventStreamItem> reader = new EventStreamReader<>(dockerClient.pullImageCmd(
-                "busybox:latest").exec(), PullEventStreamItem.class)) {
-            ;
-            assertThat(
-                    reader.readItem(),
-                    allOf(hasProperty("status", equalTo("Pulling from busybox")), hasProperty("progress", nullValue()),
-                            hasProperty("progressDetail", nullValue())));
-            assertNull(reader.readItem());
-        }
-    }
-
-    @Test
-    public void buildCanBeStreamed() throws Exception {
-
-        try (EventStreamReader<EventStreamItem> reader = new EventStreamReader<>(dockerClient.buildImageCmd(
-                new File("src/test/resources/eventStreamReaderDockerfile")).exec(), EventStreamItem.class)) {
-            assertThat(
-                    reader.readItem(),
-                    allOf(hasProperty("stream", equalTo("Step 0 : FROM busybox:latest\n")),
-                            hasProperty("error", nullValue()), hasProperty("errorDetail", nullValue())));
-            assertNull(reader.readItem());
-
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java
index eb490d7e..c3f2c007 100644
--- a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java
@@ -31,7 +31,7 @@ public class EventsCmdImplTest extends AbstractDockerClientTest {
     }
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -54,7 +54,7 @@ public class EventsCmdImplTest extends AbstractDockerClientTest {
      * This specific test may fail with boot2docker as time may not in sync with host system
      */
     @Test
-    public void testEventStreamTimeBound() throws InterruptedException, IOException {
+    public void testEventStreamTimeBound() throws Exception {
         // Don't include other tests events
         TimeUnit.SECONDS.sleep(1);
 
@@ -65,8 +65,7 @@ public class EventsCmdImplTest extends AbstractDockerClientTest {
         CountDownLatch countDownLatch = new CountDownLatch(expectedEvents);
         EventCallbackTest eventCallback = new EventCallbackTest(countDownLatch);
 
-        EventsCmd eventsCmd = dockerClient.eventsCmd(eventCallback).withSince(startTime).withUntil(endTime);
-        eventsCmd.exec();
+        dockerClient.eventsCmd().withSince(startTime).withUntil(endTime).exec(eventCallback);
 
         boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS);
 
@@ -76,15 +75,14 @@ public class EventsCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test
-    public void testEventStreaming1() throws InterruptedException, IOException {
+    public void testEventStreaming1() throws Exception {
         // Don't include other tests events
         TimeUnit.SECONDS.sleep(1);
 
         CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS);
         EventCallbackTest eventCallback = new EventCallbackTest(countDownLatch);
 
-        EventsCmd eventsCmd = dockerClient.eventsCmd(eventCallback).withSince(getEpochTime());
-        eventsCmd.exec();
+        dockerClient.eventsCmd().withSince(getEpochTime()).exec(eventCallback);
 
         generateEvents();
 
@@ -95,15 +93,14 @@ public class EventsCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test
-    public void testEventStreaming2() throws InterruptedException, IOException {
+    public void testEventStreaming2() throws Exception {
         // Don't include other tests events
         TimeUnit.SECONDS.sleep(1);
 
         CountDownLatch countDownLatch = new CountDownLatch(KNOWN_NUM_EVENTS);
         EventCallbackTest eventCallback = new EventCallbackTest(countDownLatch);
 
-        EventsCmd eventsCmd = dockerClient.eventsCmd(eventCallback).withSince(getEpochTime());
-        eventsCmd.exec();
+        dockerClient.eventsCmd().withSince(getEpochTime()).exec(eventCallback);
 
         generateEvents();
 
@@ -116,16 +113,18 @@ public class EventsCmdImplTest extends AbstractDockerClientTest {
     /**
      * This method generates {#link KNOWN_NUM_EVENTS} events
      */
-    private int generateEvents() {
+    private int generateEvents() throws Exception {
         String testImage = "busybox";
-        asString(dockerClient.pullImageCmd(testImage).exec());
+
+        dockerClient.pullImageCmd(testImage).exec(new PullResponseCallback()).awaitCompletion();
+
         CreateContainerResponse container = dockerClient.createContainerCmd(testImage).withCmd("sleep", "9999").exec();
         dockerClient.startContainerCmd(container.getId()).exec();
         dockerClient.stopContainerCmd(container.getId()).exec();
         return KNOWN_NUM_EVENTS;
     }
 
-    private class EventCallbackTest extends ResultCallbackTemplate<Event> {
+    private class EventCallbackTest extends ResultCallbackTemplate<EventCallbackTest, Event> {
 
         private final CountDownLatch countDownLatch;
 
diff --git a/src/test/java/com/github/dockerjava/core/command/ExecCreateCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ExecCreateCmdImplTest.java
index d5ec7930..139c81f5 100644
--- a/src/test/java/com/github/dockerjava/core/command/ExecCreateCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/ExecCreateCmdImplTest.java
@@ -1,23 +1,27 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
-import com.github.dockerjava.api.command.CreateContainerResponse;
-import com.github.dockerjava.api.command.ExecCreateCmdResponse;
-import com.github.dockerjava.client.AbstractDockerClientTest;
-import org.testng.ITestResult;
-import org.testng.annotations.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isEmptyString;
+import static org.hamcrest.Matchers.not;
 
 import java.lang.reflect.Method;
 import java.security.SecureRandom;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.isEmptyString;
-import static org.hamcrest.Matchers.not;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.command.ExecCreateCmdResponse;
+import com.github.dockerjava.client.AbstractDockerClientTest;
 
 @Test(groups = "integration")
 public class ExecCreateCmdImplTest extends AbstractDockerClientTest {
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java
index c3586a96..94934296 100644
--- a/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/ExecStartCmdImplTest.java
@@ -1,24 +1,28 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
-import com.github.dockerjava.api.command.CreateContainerResponse;
-import com.github.dockerjava.api.command.ExecCreateCmdResponse;
-import com.github.dockerjava.client.AbstractDockerClientTest;
-import org.testng.ITestResult;
-import org.testng.annotations.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isEmptyString;
+import static org.hamcrest.Matchers.not;
 
 import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.security.SecureRandom;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.isEmptyString;
-import static org.hamcrest.Matchers.not;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.command.ExecCreateCmdResponse;
+import com.github.dockerjava.client.AbstractDockerClientTest;
 
 @Test(groups = "integration")
 public class ExecStartCmdImplTest extends AbstractDockerClientTest {
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/FrameReaderITest.java b/src/test/java/com/github/dockerjava/core/command/FrameReaderITest.java
index 6f847ebe..5f647b1f 100644
--- a/src/test/java/com/github/dockerjava/core/command/FrameReaderITest.java
+++ b/src/test/java/com/github/dockerjava/core/command/FrameReaderITest.java
@@ -55,15 +55,15 @@ public class FrameReaderITest {
 
         AbstractDockerClientTest.CollectFramesCallback collectFramesCallback = new AbstractDockerClientTest.CollectFramesCallback();
 
-        dockerClient.logContainerCmd(dockerfileFixture.getContainerId(), collectFramesCallback).withStdOut()
+        dockerClient.logContainerCmd(dockerfileFixture.getContainerId()).withStdOut()
                 .withStdErr().withTailAll()
                 // we can't follow stream here as it blocks reading from resulting InputStream infinitely
                 // .withFollowStream()
-                .exec();
+                .exec(collectFramesCallback);
 
-        collectFramesCallback.awaitFinish();
+        collectFramesCallback.awaitCompletion();
 
-        return collectFramesCallback.frames;
+        return collectFramesCallback.items;
     }
 
     @Test
diff --git a/src/test/java/com/github/dockerjava/core/command/InfoCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/InfoCmdImplTest.java
index 19e27507..f6551d57 100644
--- a/src/test/java/com/github/dockerjava/core/command/InfoCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/InfoCmdImplTest.java
@@ -1,5 +1,9 @@
 package com.github.dockerjava.core.command;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isEmptyOrNullString;
+import static org.hamcrest.Matchers.not;
+
 import java.lang.reflect.Method;
 
 import org.testng.ITestResult;
@@ -14,15 +18,11 @@ import com.github.dockerjava.api.command.CreateContainerResponse;
 import com.github.dockerjava.api.model.Info;
 import com.github.dockerjava.client.AbstractDockerClientTest;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.isEmptyOrNullString;
-import static org.hamcrest.Matchers.not;
-
 @Test(groups = "integration")
 public class InfoCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java
index 69f4d78e..62f530bf 100644
--- a/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java
@@ -1,30 +1,33 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isEmptyString;
+import static org.hamcrest.Matchers.not;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.security.SecureRandom;
+
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
 import com.github.dockerjava.api.command.CreateContainerResponse;
 import com.github.dockerjava.api.command.ExecCreateCmdResponse;
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import com.github.dockerjava.api.command.InspectExecResponse;
 import com.github.dockerjava.client.AbstractDockerClientTest;
 import com.github.dockerjava.test.serdes.JSONTestHelper;
-import java.io.IOException;
-
-import org.testng.ITestResult;
-import org.testng.annotations.*;
-
-import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.security.SecureRandom;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.isEmptyString;
-import static org.hamcrest.Matchers.not;
 
 @Test(groups = "integration")
 public class InspectExecCmdImplTest extends AbstractDockerClientTest {
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java
index e60930d8..6346ce16 100644
--- a/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/KillContainerCmdImplTest.java
@@ -29,7 +29,7 @@ public class KillContainerCmdImplTest extends AbstractDockerClientTest {
     public static final Logger LOG = LoggerFactory.getLogger(KillContainerCmdImplTest.class);
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java
index 2f052f84..1669728c 100644
--- a/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java
@@ -35,7 +35,7 @@ import com.google.common.collect.ImmutableMap;
 public class ListContainersCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -54,12 +54,12 @@ public class ListContainersCmdImplTest extends AbstractDockerClientTest {
         super.afterMethod(result);
     }
 
-    public void testListContainers() throws DockerException {
+    public void testListContainers() throws Exception {
 
         String testImage = "busybox";
 
         // need to block until image is pulled completely
-        asString(dockerClient.pullImageCmd(testImage).exec());
+        dockerClient.pullImageCmd(testImage).exec(new PullResponseCallback()).awaitCompletion();
 
         List<Container> containers = dockerClient.listContainersCmd().withShowAll(true).exec();
         assertThat(containers, notNullValue());
@@ -102,12 +102,12 @@ public class ListContainersCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test
-    public void testListContainersWithLabelsFilter() throws DockerException {
+    public void testListContainersWithLabelsFilter() throws Exception {
 
         String testImage = "busybox";
 
         // need to block until image is pulled completely
-        asString(dockerClient.pullImageCmd(testImage).exec());
+        dockerClient.pullImageCmd(testImage).exec(new PullResponseCallback()).awaitCompletion();
 
         List<Container> containers = dockerClient.listContainersCmd().withShowAll(true).exec();
         assertThat(containers, notNullValue());
diff --git a/src/test/java/com/github/dockerjava/core/command/ListImagesCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ListImagesCmdImplTest.java
index e91641ee..d47dbb50 100644
--- a/src/test/java/com/github/dockerjava/core/command/ListImagesCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/ListImagesCmdImplTest.java
@@ -23,7 +23,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class ListImagesCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java
index 7453b340..f3c8f022 100644
--- a/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/LogContainerCmdImplTest.java
@@ -7,8 +7,6 @@ import static org.hamcrest.Matchers.not;
 
 import java.io.IOException;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
 
 import org.testng.ITestResult;
 import org.testng.annotations.AfterMethod;
@@ -17,18 +15,15 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-import com.github.dockerjava.api.DockerException;
 import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.api.command.CreateContainerResponse;
-import com.github.dockerjava.api.model.Frame;
 import com.github.dockerjava.client.AbstractDockerClientTest;
-import com.github.dockerjava.core.async.ResultCallbackTemplate;
 
 @Test(groups = "integration")
 public class LogContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -66,9 +61,9 @@ public class LogContainerCmdImplTest extends AbstractDockerClientTest {
 
         CollectFramesCallback loggingCallback = new CollectFramesCallback();
 
-        dockerClient.logContainerCmd(container.getId(), loggingCallback).withStdErr().withStdOut().exec();
+        dockerClient.logContainerCmd(container.getId()).withStdErr().withStdOut().exec(loggingCallback);
 
-        loggingCallback.awaitFinish();
+        loggingCallback.awaitCompletion();
 
         assertTrue(loggingCallback.toString().contains(snippet));
     }
@@ -98,9 +93,7 @@ public class LogContainerCmdImplTest extends AbstractDockerClientTest {
             };
         };
 
-        dockerClient.logContainerCmd("non-existing", loggingCallback).withStdErr().withStdOut().exec();
-
-        loggingCallback.awaitFinish();
+        dockerClient.logContainerCmd("non-existing").withStdErr().withStdOut().exec(loggingCallback).awaitCompletion();
     }
 
     @Test
@@ -122,21 +115,21 @@ public class LogContainerCmdImplTest extends AbstractDockerClientTest {
 
         CollectFramesCallback loggingCallback = new CollectFramesCallback();
 
-        dockerClient.logContainerCmd(container.getId(), loggingCallback).withStdErr().withStdOut().exec();
+        dockerClient.logContainerCmd(container.getId()).withStdErr().withStdOut().exec(loggingCallback);
 
         loggingCallback.close();
 
         loggingCallback = new CollectFramesCallback();
 
-        dockerClient.logContainerCmd(container.getId(), loggingCallback).withStdErr().withStdOut().exec();
+        dockerClient.logContainerCmd(container.getId()).withStdErr().withStdOut().exec(loggingCallback);
 
         loggingCallback.close();
 
         loggingCallback = new CollectFramesCallback();
 
-        dockerClient.logContainerCmd(container.getId(), loggingCallback).withStdErr().withStdOut().exec();
+        dockerClient.logContainerCmd(container.getId()).withStdErr().withStdOut().exec(loggingCallback);
 
-        loggingCallback.awaitFinish();
+        loggingCallback.awaitCompletion();
 
         assertTrue(loggingCallback.toString().contains(snippet));
     }
diff --git a/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java
index f3871e04..83c43377 100644
--- a/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java
@@ -1,34 +1,38 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
-import com.github.dockerjava.api.InternalServerErrorException;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.lang.reflect.Method;
+
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
 import com.github.dockerjava.api.NotFoundException;
+import com.github.dockerjava.api.async.ResultCallback;
 import com.github.dockerjava.api.command.InspectImageResponse;
 import com.github.dockerjava.api.command.PullImageCmd;
 import com.github.dockerjava.api.model.Info;
+import com.github.dockerjava.api.model.PullResponseItem;
 import com.github.dockerjava.client.AbstractDockerClientTest;
-import org.testng.ITestResult;
-import org.testng.annotations.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.*;
 
 @Test(groups = "integration")
 public class PullImageCmdImplTest extends AbstractDockerClientTest {
 
     private static final PullImageCmd.Exec NOP_EXEC = new PullImageCmd.Exec() {
-        @Override
-        public InputStream exec(PullImageCmd command) {
+        public Void exec(PullImageCmd command, ResultCallback<PullResponseItem> resultCallback) {
             return null;
-        }
+        };
     };
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -55,11 +59,13 @@ public class PullImageCmdImplTest extends AbstractDockerClientTest {
             fail();
         } catch (Exception e) {
             assertEquals(e.getMessage(), "authConfig was not specified");
+        } finally {
+            pullImageCmd.close();
         }
     }
 
     @Test
-    public void testPullImage() throws DockerException, IOException {
+    public void testPullImage() throws Exception {
         Info info = dockerClient.infoCmd().exec();
         LOG.info("Client info: {}", info.toString());
 
@@ -89,9 +95,11 @@ public class PullImageCmdImplTest extends AbstractDockerClientTest {
 
         LOG.info("Pulling image: {}", testImage);
 
-        InputStream response = dockerClient.pullImageCmd(testImage).exec();
+        PullResponseCallback callback = dockerClient.pullImageCmd(testImage).exec(new PullResponseCallback());
+
+        callback.awaitCompletion();
 
-        assertThat(asString(response), containsString("Download complete"));
+        assertThat(callback.toString(), containsString("Download complete"));
 
         info = dockerClient.infoCmd().exec();
         LOG.info("Client info after pull, {}", info.toString());
@@ -104,12 +112,11 @@ public class PullImageCmdImplTest extends AbstractDockerClientTest {
     }
 
     @Test
-    public void testPullNonExistingImage() throws DockerException, IOException {
+    public void testPullNonExistingImage() throws Exception {
 
         // does not throw an exception
-        InputStream is = dockerClient.pullImageCmd("xvxcv/foo").exec();
         // stream needs to be fully read in order to close the underlying connection
-        asString(is);
+        dockerClient.pullImageCmd("xvxcv/foo").exec(new PullResponseCallback()).awaitCompletion();
     }
 
 }
diff --git a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java
index 8498256a..23eff6db 100644
--- a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java
@@ -1,17 +1,24 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
-import com.github.dockerjava.api.command.CreateContainerResponse;
-import com.github.dockerjava.client.AbstractDockerClientTest;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.isEmptyString;
+import static org.hamcrest.Matchers.not;
+
+import java.lang.reflect.Method;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.ITestResult;
-import org.testng.annotations.*;
-
-import java.lang.reflect.Method;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
 
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.*;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.PushResponseItem;
+import com.github.dockerjava.client.AbstractDockerClientTest;
 
 @Test(groups = "integration")
 public class PushImageCmdImplTest extends AbstractDockerClientTest {
@@ -21,7 +28,7 @@ public class PushImageCmdImplTest extends AbstractDockerClientTest {
     String username;
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
         username = dockerClient.authConfig().getUsername();
     }
@@ -54,20 +61,28 @@ public class PushImageCmdImplTest extends AbstractDockerClientTest {
         String imageId = dockerClient.commitCmd(container.getId()).withRepository(username + "/busybox").exec();
 
         // we have to block until image is pushed
-        asString(dockerClient.pushImageCmd(username + "/busybox").exec());
+        dockerClient.pushImageCmd(username + "/busybox").exec(new PushResponseCallback()).awaitCompletion();
 
         LOG.info("Removing image: {}", imageId);
         dockerClient.removeImageCmd(imageId).exec();
 
-        String response = asString(dockerClient.pullImageCmd(username + "/busybox").exec());
+        PullResponseCallback pushCallback = dockerClient.pullImageCmd(username + "/busybox")
+                .exec(new PullResponseCallback()).awaitCompletion();
 
-        assertThat(response, not(containsString("HTTP code: 404")));
+        assertThat(pushCallback.toString(), not(containsString("HTTP code: 404")));
     }
 
     @Test
-    public void pushExistentImage() throws Exception {
+    public void pushNonExistentImage() throws Exception {
+
+        PushResponseCallback callback = dockerClient.pushImageCmd(username + "/xxx").exec(new PushResponseCallback())
+                .awaitCompletion();
+
+        assertThat(callback.toString(), containsString("error"));
+    }
+
+    public static class PushResponseCallback extends CollectStreamItemCallback<PushResponseCallback, PushResponseItem> {
 
-        assertThat(asString(dockerClient.pushImageCmd(username + "/xxx").exec()), containsString("error"));
     }
 
 }
diff --git a/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java
index 22fbb096..3241f073 100644
--- a/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/RemoveContainerCmdImplTest.java
@@ -31,7 +31,7 @@ public class RemoveContainerCmdImplTest extends AbstractDockerClientTest {
     public static final Logger LOG = LoggerFactory.getLogger(RemoveContainerCmdImplTest.class);
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java
index 1c0f3db1..75f58828 100644
--- a/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/RemoveImageCmdImplTest.java
@@ -32,7 +32,7 @@ public class RemoveImageCmdImplTest extends AbstractDockerClientTest {
     public static final Logger LOG = LoggerFactory.getLogger(RemoveImageCmdImplTest.class);
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java
index 86680016..1258cd7d 100644
--- a/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/RestartContainerCmdImplTest.java
@@ -25,7 +25,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class RestartContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/SaveImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/SaveImageCmdImplTest.java
index 9facdc2d..ffc81d4e 100644
--- a/src/test/java/com/github/dockerjava/core/command/SaveImageCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/SaveImageCmdImplTest.java
@@ -1,8 +1,11 @@
 package com.github.dockerjava.core.command;
 
-import com.github.dockerjava.api.DockerException;
-import com.github.dockerjava.api.command.CreateContainerResponse;
-import com.github.dockerjava.client.AbstractDockerClientTest;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+
+import java.io.InputStream;
+import java.lang.reflect.Method;
+
 import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -13,16 +16,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.isEmptyString;
-import static org.hamcrest.Matchers.not;
+import com.github.dockerjava.client.AbstractDockerClientTest;
 
 @Test(groups = "integration")
 public class SaveImageCmdImplTest extends AbstractDockerClientTest {
@@ -31,7 +25,7 @@ public class SaveImageCmdImplTest extends AbstractDockerClientTest {
     String username;
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/SearchImagesCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/SearchImagesCmdImplTest.java
index f61ff078..6b3d2adb 100644
--- a/src/test/java/com/github/dockerjava/core/command/SearchImagesCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/SearchImagesCmdImplTest.java
@@ -26,7 +26,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class SearchImagesCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java
index d690f4e1..ae323c4c 100644
--- a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java
@@ -46,7 +46,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class StartContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/StatsCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StatsCmdImplTest.java
index 5ccb0103..cd6646e6 100644
--- a/src/test/java/com/github/dockerjava/core/command/StatsCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/StatsCmdImplTest.java
@@ -17,7 +17,6 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-import com.github.dockerjava.api.DockerException;
 import com.github.dockerjava.api.command.CreateContainerResponse;
 import com.github.dockerjava.api.command.StatsCmd;
 import com.github.dockerjava.api.model.Statistics;
@@ -30,7 +29,7 @@ public class StatsCmdImplTest extends AbstractDockerClientTest {
     private static int NUM_STATS = 5;
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
@@ -54,7 +53,6 @@ public class StatsCmdImplTest extends AbstractDockerClientTest {
         TimeUnit.SECONDS.sleep(1);
 
         CountDownLatch countDownLatch = new CountDownLatch(NUM_STATS);
-        StatsCallbackTest statsCallback = new StatsCallbackTest(countDownLatch);
 
         String containerName = "generated_" + new SecureRandom().nextInt();
 
@@ -65,8 +63,7 @@ public class StatsCmdImplTest extends AbstractDockerClientTest {
 
         dockerClient.startContainerCmd(container.getId()).exec();
 
-        StatsCmd statsCmd = dockerClient.statsCmd(statsCallback).withContainerId(container.getId());
-        statsCmd.exec();
+        StatsCallbackTest statsCallback = dockerClient.statsCmd().withContainerId(container.getId()).exec(new StatsCallbackTest(countDownLatch));
 
         countDownLatch.await(3, TimeUnit.SECONDS);
         boolean gotStats = statsCallback.gotStats();
@@ -84,7 +81,7 @@ public class StatsCmdImplTest extends AbstractDockerClientTest {
 
     }
 
-    private class StatsCallbackTest extends ResultCallbackTemplate<Statistics> {
+    private class StatsCallbackTest extends ResultCallbackTemplate<StatsCallbackTest, Statistics> {
         private final CountDownLatch countDownLatch;
 
         private boolean gotStats = false;
diff --git a/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java
index 8a2a2f13..1342471c 100644
--- a/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/StopContainerCmdImplTest.java
@@ -29,7 +29,7 @@ public class StopContainerCmdImplTest extends AbstractDockerClientTest {
     public static final Logger LOG = LoggerFactory.getLogger(StopContainerCmdImplTest.class);
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java
index b7c8bc4f..116d2b68 100644
--- a/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/TagImageCmdImplTest.java
@@ -12,7 +12,6 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-import com.github.dockerjava.api.DockerException;
 import com.github.dockerjava.api.NotFoundException;
 import com.github.dockerjava.client.AbstractDockerClientTest;
 
@@ -22,7 +21,7 @@ public class TagImageCmdImplTest extends AbstractDockerClientTest {
     public static final Logger LOG = LoggerFactory.getLogger(TagImageCmdImplTest.class);
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/VersionCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/VersionCmdImplTest.java
index edb5560e..7bac10c6 100644
--- a/src/test/java/com/github/dockerjava/core/command/VersionCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/VersionCmdImplTest.java
@@ -18,7 +18,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class VersionCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }
 
diff --git a/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java
index 57650649..3b5172b9 100644
--- a/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java
+++ b/src/test/java/com/github/dockerjava/core/command/WaitContainerCmdImplTest.java
@@ -25,7 +25,7 @@ import com.github.dockerjava.client.AbstractDockerClientTest;
 public class WaitContainerCmdImplTest extends AbstractDockerClientTest {
 
     @BeforeTest
-    public void beforeTest() throws DockerException {
+    public void beforeTest() throws Exception {
         super.beforeTest();
     }