[REEF-2028] A new module containing the new .Net bridge (#1477)

* [REEF-2025] A new module containing the new Java bridge

    This Jira introduces a new Java bridge for Drivers implemented in
    alternative languages. It provides the following artifacts (note: client
    driver refers to the application driver implemented in an alternative
    programming language):

	1. A generic framework for passing information between the Java driver and the client driver.
	2. A gRPC based implementation of the bridge that passes information via protocol buffers over gRPC.
	3. Protocol buffer definitions for all information that flows between the Java driver and the client driver.
	4. A Java implementation of the driver client that can be used for developing unit tests and serve as a template for implementing a driver client (say in C#).
	5. Test cases to fail based unit tests that cover the Java bridge and client.

Pull Request:
    Closes #1477
diff --git a/.gitignore b/.gitignore
index 1c6af07..f7272db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,10 +8,9 @@
 # Files generated during builds
 # ----------------------------------------------------------------------
 target
-generated
+generated-sources
 build
 StyleCop.Cache
-dependency-reduced-pom.xml
 #
 # ----------------------------------------------------------------------
 # IDE settings
diff --git a/lang/common/proto/bridge/ClientProtocol.proto b/lang/common/proto/bridge/ClientProtocol.proto
index 3013b2f..b66af19 100644
--- a/lang/common/proto/bridge/ClientProtocol.proto
+++ b/lang/common/proto/bridge/ClientProtocol.proto
@@ -21,10 +21,77 @@
 
 option java_package = "org.apache.reef.bridge.proto";
 option java_outer_classname = "ClientProtocol";
-option csharp_namespace = "Org.Apache.REEF.Bridge.Proto";
+option csharp_namespace = "Org.Apache.REEF.Bridge.Core.Proto";
 
 package driverbridge;
 
+import "DriverCommonProtocol.proto";
+
+// Bridge Client RPC and messages
+service BridgeClient {
+
+  rpc RegisterREEFClient (REEFClientRegistration) returns (Void) {}
+
+  rpc JobMessageHandler (JobMessageEvent) returns (Void) {}
+
+  rpc JobSumittedHandler (JobSubmittedEvent) returns (Void) {}
+
+  rpc JobRunningHandler (JobRunningEvent) returns (Void) {}
+
+  rpc JobCompletedHandler (JobCompletedEvent) returns (Void) {}
+
+  rpc JobFailedHandler (JobFailedEvent) returns (Void) {}
+
+  rpc RuntimeErrorHandler (ExceptionInfo) returns (Void) {}
+
+  rpc WakeErrorHandler (ExceptionInfo) returns (Void) {}
+}
+
+message REEFClientRegistration {
+  string hostname = 1;
+  uint32 port = 2;
+}
+
+message JobMessageEvent {
+  string job_id = 1;
+  bytes message = 2;
+}
+
+message JobSubmittedEvent {
+  string job_id = 1;
+}
+
+message JobRunningEvent {
+  string job_id = 1;
+}
+
+message JobCompletedEvent {
+  string job_id = 1;
+}
+
+message JobFailedEvent {
+  string job_id = 1;
+  ExceptionInfo exception = 2;
+}
+
+// REEF Client RPC and messages
+service REEFClient {
+
+  rpc DriverControlHandler (DriverControlOp) returns (Void) {}
+}
+
+message DriverControlOp {
+  string job_id = 1;
+
+  bytes message = 2;
+
+  enum Operation {
+    CLOSE = 0;
+    MESSAGE = 1;
+  }
+  Operation operation = 3;
+}
+
 /*
  * Local runtime parameters.
  */
@@ -70,9 +137,24 @@
 }
 
 /*
- * Mesos runtime parameters.
+ * HD Insight runtime parameters.
  */
-message MesosRuntimeParameters {
+message HDIRuntimeParameters {
+  bool unsafe = 1;
+
+  // HD Insight Account Information
+  string hdi_user_name = 2;
+
+  string hdi_password = 3;
+
+  string hdi_url = 4;
+
+  // Azure Storage Account Information
+  string azure_storage_account_name = 5;
+
+  string azure_storage_account_key = 6;
+
+  string azure_storage_container_name = 7;
 }
 
 /*
@@ -92,7 +174,7 @@
     LocalRuntimeParameters local_runtime = 5;
     YarnRuntimeParameters yarn_runtime = 6;
     AzureBatchRuntimeParameters azbatch_runtime = 7;
-    MesosRuntimeParameters mesos_runtime = 8;
+    HDIRuntimeParameters hdi_runtime = 8;
   }
 
   // The command to launch the driver client
diff --git a/lang/common/proto/bridge/DriverClientProtocol.proto b/lang/common/proto/bridge/DriverClientProtocol.proto
index 7411e8d..2f29c09 100644
--- a/lang/common/proto/bridge/DriverClientProtocol.proto
+++ b/lang/common/proto/bridge/DriverClientProtocol.proto
@@ -23,7 +23,7 @@
 option java_multiple_files = true;
 option java_package = "org.apache.reef.bridge.proto";
 option java_outer_classname = "DriverClientProtocol";
-option csharp_namespace = "Org.Apache.REEF.Bridge.Proto";
+option csharp_namespace = "Org.Apache.REEF.Bridge.Core.Proto";
 
 package driverbridge;
 
@@ -121,6 +121,7 @@
 // Information associated with an alarm that was set.
 message AlarmTriggerInfo {
   string alarm_id = 1;
+  int64 timestamp = 2;
 }
 
 // Evaluator descriptor information.
@@ -156,6 +157,9 @@
      string message = 1;
      repeated string failed_contexts = 2;
      string failed_task_id = 3;
+
+     // Exception specific to failed evaluator
+     ExceptionInfo exception = 5;
   }
   FailureInfo failure = 2;
 
diff --git a/lang/common/proto/bridge/DriverCommonProtocol.proto b/lang/common/proto/bridge/DriverCommonProtocol.proto
index 439b203..cc8e17c 100644
--- a/lang/common/proto/bridge/DriverCommonProtocol.proto
+++ b/lang/common/proto/bridge/DriverCommonProtocol.proto
@@ -22,7 +22,7 @@
 // option java_generic_services = true;
 option java_multiple_files = true;
 option java_package = "org.apache.reef.bridge.proto";
-option csharp_namespace = "Org.Apache.REEF.Bridge.Proto";
+option csharp_namespace = "Org.Apache.REEF.Bridge.Core.Proto";
 
 package driverbridge;
 
diff --git a/lang/common/proto/bridge/DriverServiceProtocol.proto b/lang/common/proto/bridge/DriverServiceProtocol.proto
index d9f8ffa..7f65563 100644
--- a/lang/common/proto/bridge/DriverServiceProtocol.proto
+++ b/lang/common/proto/bridge/DriverServiceProtocol.proto
@@ -23,7 +23,7 @@
 option java_multiple_files = true;
 option java_package = "org.apache.reef.bridge.proto";
 option java_outer_classname = "DriverBridgeProtocol";
-option csharp_namespace = "Org.Apache.REEF.Bridge.Proto";
+option csharp_namespace = "Org.Apache.REEF.Bridge.Core.Proto";
 
 package driverbridge;
 
@@ -82,6 +82,8 @@
   bool relax_locality = 7;
 
   string runtime_name = 8;
+
+  string node_label = 9;
 }
 
 // Request for an alarm to be set
@@ -115,8 +117,11 @@
   // Context configuration
   string context_configuration = 6;
 
+  // Service configuration
+  string service_configuration = 7;
+
   // Task configuration
-  string task_configuration = 7;
+  string task_configuration = 8;
 
   message EvaluatorProcessRequest {
     int32 memory_mb = 1;
@@ -128,8 +133,15 @@
     string standard_err = 4;
 
     repeated string options = 5;
+
+    enum Type {
+      JVM = 0;
+      CLR = 1;
+      DOTNET = 2;
+    }
+    Type process_type = 10;
   }
-  EvaluatorProcessRequest set_process = 8;
+  EvaluatorProcessRequest set_process = 10;
 }
 
 // Active context request.
diff --git a/lang/cs/App.config b/lang/cs/App.config
index 51d8c4f..fde648e 100644
--- a/lang/cs/App.config
+++ b/lang/cs/App.config
@@ -38,7 +38,11 @@
       <dependentAssembly>
         <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
         <bindingRedirect oldVersion="0.0.0.0-5.8.1.0" newVersion="5.8.1.0" />
+	  </dependentAssembly>
+	  <dependentAssembly>
+        <assemblyIdentity name="System.Interactive.Async" publicKeyToken="94bc3704cddfc263" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
       </dependentAssembly>
     </assemblyBinding>
   </runtime>
-</configuration>
+</configuration>
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/ClientConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/ClientConfiguration.cs
new file mode 100644
index 0000000..1a498e8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/ClientConfiguration.cs
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Util;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    public sealed class ClientConfiguration : ConfigurationModuleBuilder
+    {
+        public static readonly OptionalParameter<IObserver<IRunningJob>> OnRunningJob = new OptionalParameter<IObserver<IRunningJob>>();
+
+        public static readonly OptionalParameter<IObserver<ISubmittedJob>> OnSubmittedJob = new OptionalParameter<IObserver<ISubmittedJob>>();
+
+        public static readonly OptionalParameter<IObserver<ICompletedJob>> OnCompletedJob = new OptionalParameter<IObserver<ICompletedJob>>();
+
+        public static readonly OptionalParameter<IObserver<IFailedJob>> OnFailedJob = new OptionalParameter<IObserver<IFailedJob>>();
+
+        public static readonly OptionalParameter<IObserver<IJobMessage>> OnJobMessage = new OptionalParameter<IObserver<IJobMessage>>();
+
+        public static readonly OptionalParameter<IObserver<IFailedRuntime>> OnFailedRuntime = new OptionalParameter<IObserver<IFailedRuntime>>();
+
+        public static readonly OptionalParameter<IObserver<IWakeError>> OnWakeError = new OptionalParameter<IObserver<IWakeError>>();
+
+        public static ConfigurationModule ConfigurationModule => new ClientConfiguration()
+                    .BindNamedParameter(GenericType<ClientParameters.RunningJobHandler>.Class, OnRunningJob)
+                    .BindNamedParameter(GenericType<ClientParameters.SubmittedJobHandler>.Class, OnSubmittedJob)
+                    .BindNamedParameter(GenericType<ClientParameters.CompletedJobHandler>.Class, OnCompletedJob)
+                    .BindNamedParameter(GenericType<ClientParameters.FailedJobHandler>.Class, OnFailedJob)
+                    .BindNamedParameter(GenericType<ClientParameters.JobMessageHandler>.Class, OnJobMessage)
+                    .BindNamedParameter(GenericType<ClientParameters.FailedRuntimeHandler>.Class, OnFailedRuntime)
+                    .BindNamedParameter(GenericType<ClientParameters.WakeErrorHandler>.Class, OnWakeError)
+                    .Build();
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/ClientParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/ClientParameters.cs
new file mode 100644
index 0000000..edd9f8f
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/ClientParameters.cs
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Default;
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    /// <summary>
+    /// Parameters associated with the client.
+    /// </summary>
+    public sealed class ClientParameters
+    {
+        [NamedParameter("completed job handler", defaultClass: typeof(DefaultCompletedJobHandler))]
+        public sealed class CompletedJobHandler : Name<IObserver<ICompletedJob>>
+        {
+        }
+
+        [NamedParameter("failed job handler", defaultClass: typeof(DefaultFailedJobHandler))]
+        public sealed class FailedJobHandler : Name<IObserver<IFailedJob>>
+        {
+        }
+
+        [NamedParameter("failed runtime handler", defaultClass: typeof(DefaultFailedRuntimeHandler))]
+        public sealed class FailedRuntimeHandler : Name<IObserver<IFailedRuntime>>
+        {
+        }
+
+        [NamedParameter("job message handler", defaultClass: typeof(DefaultJobMessageHandler))]
+        public sealed class JobMessageHandler : Name<IObserver<IJobMessage>>
+        {
+        }
+
+        [NamedParameter("running job handler", defaultClass: typeof(DefaultRunningJobHandler))]
+        public sealed class RunningJobHandler : Name<IObserver<IRunningJob>>
+        {
+        }
+
+        [NamedParameter("submitted job handler", defaultClass: typeof(DefaultSubmittedJobHandler))]
+        public sealed class SubmittedJobHandler : Name<IObserver<ISubmittedJob>>
+        {
+        }
+
+        [NamedParameter("wake error handler", defaultClass: typeof(DefaultWakeErrorHandler))]
+        public sealed class WakeErrorHandler : Name<IObserver<IWakeError>>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverApplicationConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverApplicationConfiguration.cs
new file mode 100644
index 0000000..68255a0
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverApplicationConfiguration.cs
@@ -0,0 +1,219 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Driver;
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Utilities.Attributes;
+using Org.Apache.REEF.Wake.Time;
+using System;
+using System.Diagnostics;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    /// <summary>
+    /// Fill this out to configure a Driver.
+    /// </summary>
+    [ClientSide]
+    public sealed class DriverApplicationConfiguration : ConfigurationModuleBuilder
+    {
+        /// <summary>
+        /// The event handler called after the Driver started.
+        /// </summary>
+        public static readonly RequiredImpl<IObserver<IDriverStarted>> OnDriverStarted =
+            new RequiredImpl<IObserver<IDriverStarted>>();
+
+        /// <summary>
+        /// The event handler called when the Driver has been stopped.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IDriverStopped>> OnDriverStopped =
+            new OptionalImpl<IObserver<IDriverStopped>>();
+
+        /// <summary>
+        /// The event handler invoked when driver restarts
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IDriverRestarted>> OnDriverRestarted =
+            new OptionalImpl<IObserver<IDriverRestarted>>();
+
+        /// <summary>
+        /// Event handler for allocated evaluators. Defaults to returning the evaluator if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IAllocatedEvaluator>> OnEvaluatorAllocated =
+            new OptionalImpl<IObserver<IAllocatedEvaluator>>();
+
+        /// <summary>
+        /// Event handler for completed evaluators. Defaults to logging if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<ICompletedEvaluator>> OnEvaluatorCompleted =
+            new OptionalImpl<IObserver<ICompletedEvaluator>>();
+
+        /// <summary>
+        /// Event handler for failed evaluators. Defaults to job failure if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IFailedEvaluator>> OnEvaluatorFailed =
+            new OptionalImpl<IObserver<IFailedEvaluator>>();
+
+        /// <summary>
+        /// Event handler for task messages. Defaults to logging if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<ITaskMessage>> OnTaskMessage =
+            new OptionalImpl<IObserver<ITaskMessage>>();
+
+        /// <summary>
+        /// Event handler for completed tasks. Defaults to closing the context the task ran on if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<ICompletedTask>> OnTaskCompleted =
+            new OptionalImpl<IObserver<ICompletedTask>>();
+
+        /// <summary>
+        /// Event handler for failed tasks. Defaults to job failure if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IFailedTask>> OnTaskFailed =
+            new OptionalImpl<IObserver<IFailedTask>>();
+
+        ///// <summary>
+        ///// Event handler for running tasks. Defaults to logging if not bound.
+        ///// </summary>
+        public static readonly OptionalImpl<IObserver<IRunningTask>> OnTaskRunning =
+            new OptionalImpl<IObserver<IRunningTask>>();
+
+        ///// <summary>
+        ///// Event handler for running task received during driver restart. Defaults to logging if not bound.
+        ///// </summary>
+        public static readonly OptionalImpl<IObserver<IRunningTask>> OnDriverRestartTaskRunning =
+            new OptionalImpl<IObserver<IRunningTask>>();
+
+        /// <summary>
+        /// Event handler for suspended tasks. Defaults to job failure if not bound.
+        /// </summary>
+        /// <remarks>
+        /// Rationale: many jobs don't support task suspension. Hence, this parameter should be optional. The only sane default is
+        /// to crash the job, then.
+        /// </remarks>
+        public static readonly OptionalImpl<IObserver<ISuspendedTask>> OnTaskSuspended =
+            new OptionalImpl<IObserver<ISuspendedTask>>();
+
+        /// <summary>
+        /// Event handler for active context. Defaults to closing the context if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IActiveContext>> OnContextActive =
+            new OptionalImpl<IObserver<IActiveContext>>();
+
+        /// <summary>
+        /// Event handler for active context received during driver restart. Defaults to closing the context if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IActiveContext>> OnDriverRestartContextActive =
+            new OptionalImpl<IObserver<IActiveContext>>();
+
+        /// <summary>
+        /// Event handler for closed context. Defaults to logging if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IClosedContext>> OnContextClosed =
+            new OptionalImpl<IObserver<IClosedContext>>();
+
+        /// <summary>
+        /// Event handler for closed context. Defaults to job failure if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IFailedContext>> OnContextFailed =
+            new OptionalImpl<IObserver<IFailedContext>>();
+
+        /// <summary>
+        /// Event handler for context messages. Defaults to logging if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IContextMessage>> OnContextMessage =
+            new OptionalImpl<IObserver<IContextMessage>>();
+
+        /// <summary>
+        /// Event handler for driver restart completed. Defaults to logging if not bound.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<IDriverRestartCompleted>> OnDriverRestartCompleted =
+            new OptionalImpl<IObserver<IDriverRestartCompleted>>();
+
+        ///// <summary>
+        ///// Event handler for driver restart failed evaluator event received during driver restart. Defaults to job failure if not bound.
+        ///// </summary>
+        public static readonly OptionalImpl<IObserver<IFailedEvaluator>> OnDriverRestartEvaluatorFailed =
+            new OptionalImpl<IObserver<IFailedEvaluator>>();
+
+        /// <summary>
+        /// Event handler for client close.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<byte[]>> OnClientClose = new OptionalImpl<IObserver<byte[]>>();
+
+        /// <summary>
+        /// Event handler for client close with message.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<byte[]>> OnClientCloseWithMessage = new OptionalImpl<IObserver<byte[]>>();
+
+        /// <summary>
+        /// Event handler for client message.
+        /// </summary>
+        public static readonly OptionalImpl<IObserver<byte[]>> OnClientMessage = new OptionalImpl<IObserver<byte[]>>();
+
+        /// <summary>
+        /// The trace level of the TraceListener
+        /// </summary>
+        public static readonly OptionalParameter<string> CustomTraceLevel = new OptionalParameter<string>();
+
+        /// <summary>
+        /// Additional set of trace listeners provided by client
+        /// </summary>
+        public static readonly OptionalParameter<TraceListener> CustomTraceListeners =
+            new OptionalParameter<TraceListener>();
+
+        public static ConfigurationModule ConfigurationModule => new DriverApplicationConfiguration()
+            .BindImplementation(GenericType<IClock>.Class, GenericType<BridgeClock>.Class)
+            .BindImplementation(GenericType<IEvaluatorRequestor>.Class,
+                GenericType<DriverBridgeEvaluatorRequestor>.Class)
+
+            // Event handlers
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverStartedHandlers>.Class, OnDriverStarted)
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverStopHandlers>.Class, OnDriverStopped)
+            .BindSetEntry(GenericType<DriverApplicationParameters.AllocatedEvaluatorHandlers>.Class, OnEvaluatorAllocated)
+            .BindSetEntry(GenericType<DriverApplicationParameters.ActiveContextHandlers>.Class, OnContextActive)
+            .BindSetEntry(GenericType<DriverApplicationParameters.TaskMessageHandlers>.Class, OnTaskMessage)
+            .BindSetEntry(GenericType<DriverApplicationParameters.FailedTaskHandlers>.Class, OnTaskFailed)
+            .BindSetEntry(GenericType<DriverApplicationParameters.RunningTaskHandlers>.Class, OnTaskRunning)
+            .BindSetEntry(GenericType<DriverApplicationParameters.SuspendedTaskHandlers>.Class, OnTaskSuspended)
+            .BindSetEntry(GenericType<DriverApplicationParameters.FailedEvaluatorHandlers>.Class, OnEvaluatorFailed)
+            .BindSetEntry(GenericType<DriverApplicationParameters.CompletedEvaluatorHandlers>.Class, OnEvaluatorCompleted)
+            .BindSetEntry(GenericType<DriverApplicationParameters.CompletedTaskHandlers>.Class, OnTaskCompleted)
+            .BindSetEntry(GenericType<DriverApplicationParameters.ClosedContextHandlers>.Class, OnContextClosed)
+            .BindSetEntry(GenericType<DriverApplicationParameters.FailedContextHandlers>.Class, OnContextFailed)
+            .BindSetEntry(GenericType<DriverApplicationParameters.ContextMessageHandlers>.Class, OnContextMessage)
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverRestartCompletedHandlers>.Class,
+                OnDriverRestartCompleted)
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverRestartedHandlers>.Class, OnDriverRestarted)
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverRestartActiveContextHandlers>.Class,
+                OnDriverRestartContextActive)
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverRestartRunningTaskHandlers>.Class,
+                OnDriverRestartTaskRunning)
+            .BindSetEntry(GenericType<DriverApplicationParameters.DriverRestartFailedEvaluatorHandlers>.Class,
+                OnDriverRestartEvaluatorFailed)
+            .BindSetEntry(GenericType<DriverApplicationParameters.ClientCloseHandlers>.Class, OnClientClose)
+            .BindSetEntry(GenericType<DriverApplicationParameters.ClientCloseWithMessageHandlers>.Class, OnClientCloseWithMessage)
+            .BindSetEntry(GenericType<DriverApplicationParameters.ClientMessageHandlers>.Class, OnClientMessage)
+            .BindSetEntry(GenericType<DriverApplicationParameters.TraceListeners>.Class, CustomTraceListeners)
+            .BindNamedParameter(GenericType<DriverApplicationParameters.TraceLevel>.Class, CustomTraceLevel)
+            .Build();
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverApplicationParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverApplicationParameters.cs
new file mode 100644
index 0000000..df72f50
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverApplicationParameters.cs
@@ -0,0 +1,164 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Bridge;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Defaults;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    public sealed class DriverApplicationParameters
+    {
+        [NamedParameter(documentation: "The start point for application logic. Event fired after the Driver is done initializing.")]
+        public sealed class DriverStartedHandlers : Name<ISet<IObserver<IDriverStarted>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when driver stops.")]
+        public sealed class DriverStopHandlers : Name<ISet<IObserver<IDriverStopped>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when an evaluator completes.", defaultClasses: new[] { typeof(DefaultEvaluatorCompletionHandler) })]
+        public class CompletedEvaluatorHandlers : Name<ISet<IObserver<ICompletedEvaluator>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when an allocated evaluator is given to the client.",
+            defaultClasses: new[] { typeof(DefaultEvaluatorAllocationHandler) })]
+        public sealed class AllocatedEvaluatorHandlers : Name<ISet<IObserver<IAllocatedEvaluator>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when an exception occurs on a running evaluator.", defaultClasses: new[] { typeof(DefaultEvaluatorFailureHandler) })]
+        public class FailedEvaluatorHandlers : Name<ISet<IObserver<IFailedEvaluator>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Handler for IActiveContext.", defaultClasses: new[] { typeof(DefaultContextActiveHandler) })]
+        public sealed class ActiveContextHandlers : Name<ISet<IObserver<IActiveContext>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Handler for ClosedContext.", defaultClasses: new[] { typeof(DefaultContextClosureHandler) })]
+        public sealed class ClosedContextHandlers : Name<ISet<IObserver<IClosedContext>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Handler for ContextMessage.", defaultClasses: new[] { typeof(DefaultContextMessageHandler) })]
+        public sealed class ContextMessageHandlers : Name<ISet<IObserver<IContextMessage>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Handler for FailedContext.", defaultClasses: new[] { typeof(DefaultContextFailureHandler) })]
+        public sealed class FailedContextHandlers : Name<ISet<IObserver<IFailedContext>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Running task handler.", defaultClasses: new[] { typeof(DefaultTaskRunningHandler) })]
+        public sealed class RunningTaskHandlers : Name<ISet<IObserver<IRunningTask>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Completed task handler.", defaultClasses: new[] { typeof(DefaultTaskCompletionHandler) })]
+        public sealed class CompletedTaskHandlers : Name<ISet<IObserver<ICompletedTask>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Task exception handler.", defaultClasses: new[] { typeof(DefaultTaskFailureHandler) })]
+        public sealed class FailedTaskHandlers : Name<ISet<IObserver<IFailedTask>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Suspended task handler.", defaultClasses: new[] { typeof(DefaultTaskSuspensionHandler) })]
+        public sealed class SuspendedTaskHandlers : Name<ISet<IObserver<ISuspendedTask>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Task message handler.", defaultClasses: new[] { typeof(DefaultTaskMessageHandler) })]
+        public class TaskMessageHandlers : Name<ISet<IObserver<ITaskMessage>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when driver is restarted, after CLR bridge is set up.")]
+        public sealed class DriverRestartedHandlers : Name<ISet<IObserver<IDriverRestarted>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when an evaluator has failed in the Driver Restart process.",
+            defaultClasses: new[] { typeof(DefaultEvaluatorFailureHandler) })]
+        public sealed class DriverRestartFailedEvaluatorHandlers : Name<ISet<IObserver<IFailedEvaluator>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Handler for IActiveContext received during driver restart.",
+            defaultClasses: new[] { typeof(DefaultDriverRestartContextActiveHandler) })]
+        public sealed class DriverRestartActiveContextHandlers : Name<ISet<IObserver<IActiveContext>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Called when driver restart is completed.",
+            defaultClasses: new[] { typeof(DefaultDriverRestartCompletedHandler) })]
+        public sealed class DriverRestartCompletedHandlers : Name<ISet<IObserver<IDriverRestartCompleted>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Running task during driver restart handler.",
+            defaultClasses: new[] { typeof(DefaultDriverRestartTaskRunningHandler) })]
+        public sealed class DriverRestartRunningTaskHandlers : Name<ISet<IObserver<IRunningTask>>>
+        {
+        }
+
+        [NamedParameter("Client message handlers", defaultClasses: new[] { typeof(DefaultClientMessageHandler) })]
+        public sealed class ClientMessageHandlers : Name<ISet<IObserver<byte[]>>>
+        {
+        }
+
+        [NamedParameter("Client close with message event handlers", defaultClasses: new[] { typeof(DefaultClientCloseWithMessageHandler) })]
+        public sealed class ClientCloseWithMessageHandlers : Name<ISet<IObserver<byte[]>>>
+        {
+        }
+
+        [NamedParameter("Client close event handlers", defaultClasses: new[] { typeof(DefaultClientCloseHandler) })]
+        public sealed class ClientCloseHandlers : Name<ISet<IObserver<byte[]>>>
+        {
+        }
+
+        [NamedParameter(documentation: "Http Event Handlers.", defaultClasses: new[] { typeof(DefaultHttpHandler) })]
+        public sealed class HttpEventHandlers : Name<ISet<IHttpHandler>>
+        {
+        }
+
+        [NamedParameter("Custom Trace Level", "DriverTraceLevel", defaultValue: "Info")]
+        public class TraceLevel : Name<string>
+        {
+        }
+
+        [NamedParameter("Additional trace listeners supplied by client", "DriverTraceListeners", null,
+            defaultClasses: new[] { typeof(DefaultCustomTraceListener) })]
+        public sealed class TraceListeners : Name<ISet<TraceListener>>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverRuntimeConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverRuntimeConfiguration.cs
new file mode 100644
index 0000000..b3428f8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverRuntimeConfiguration.cs
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Util;
+using System;
+using System.IO;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    /// <summary>
+    /// Configuration Module for the driver runtime, which corresponds to the
+    /// Java driver.
+    /// </summary>
+    public sealed class DriverRuntimeConfiguration : ConfigurationModuleBuilder
+    {
+        /// <summary>
+        /// The Job identifier.
+        /// </summary>
+        public static readonly RequiredParameter<string> JobId = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Job submission directory where related job files are staged for submission.
+        /// </summary>
+        public static readonly OptionalParameter<string> JobSubmissionDirectory = new OptionalParameter<string>();
+
+        /// <summary>
+        /// How many CPU cores should be dedicated to the driver.
+        /// </summary>
+        public static readonly OptionalParameter<int> DriverCpuCores = new OptionalParameter<int>();
+
+        /// <summary>
+        /// How much memory in MegaBytes should be dedicated to the driver.
+        /// </summary>
+        public static readonly OptionalParameter<int> DriverMemory = new OptionalParameter<int>();
+
+        /// <summary>
+        /// Assembiles that should be present on the driver and all evaluators.
+        /// </summary>
+        public static readonly OptionalParameter<string> GlobalAssemblies = new OptionalParameter<string>();
+
+        /// <summary>
+        /// Assembiles that should be present only on the driver.
+        /// </summary>
+        public static readonly OptionalParameter<string> LocalAssemblies = new OptionalParameter<string>();
+
+        /// <summary>
+        /// Files that should be present on the driver and all evaluators.
+        /// </summary>
+        public static readonly OptionalParameter<string> GlobalFiles = new OptionalParameter<string>();
+
+        /// <summary>
+        /// Files that should be present only on the driver.
+        /// </summary>
+        public static readonly OptionalParameter<string> LocalFiles = new OptionalParameter<string>();
+
+        /// <summary>
+        /// Indicates whether support for driver restart should be enabled.
+        /// </summary>
+        public static readonly OptionalParameter<bool> EnableDriverRestart = new OptionalParameter<bool>();
+
+        /// <summary>
+        /// How long should we wait for evaluators to checkin with the restarted driver before
+        /// considering them dead.
+        /// </summary>
+        public static readonly OptionalParameter<int> RestartEvaluatorRecoverySeconds = new OptionalParameter<int>();
+
+        /// <summary>
+        /// The start TCP port to use for driver evaluator communication.
+        /// </summary>
+        public static readonly OptionalParameter<int> TcpPortRangeBegin = new OptionalParameter<int>();
+
+        /// <summary>
+        /// The port range for driver evaluator communication.
+        /// </summary>
+        public static readonly OptionalParameter<int> TcpPortRangeCount = new OptionalParameter<int>();
+
+        /// <summary>
+        /// How many ports should we try before giving up.
+        /// </summary>
+        public static readonly OptionalParameter<int> TcpPortRangeTryCount = new OptionalParameter<int>();
+
+        /// <summary>
+        /// The intended operating system on which the driver and evaluators will run.
+        /// </summary>
+        public static readonly OptionalImpl<OsType> OsType = new OptionalImpl<OsType>();
+
+        public static ConfigurationModule ConfigurationModule => new DriverRuntimeConfiguration()
+            .BindImplementation(GenericType<OsType>.Class, OsType)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.JobId>.Class, JobId)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.JobSubmissionDirectory>.Class, JobSubmissionDirectory)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.DriverCpuCores>.Class, DriverCpuCores)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.DriverMemory>.Class, DriverMemory)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.EnableDriverRestart>.Class, EnableDriverRestart)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.RestartEvaluatorRecoverySeconds>.Class, RestartEvaluatorRecoverySeconds)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.TcpPortRangeBegin>.Class, TcpPortRangeBegin)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.TcpPortRangeCount>.Class, TcpPortRangeCount)
+            .BindNamedParameter(GenericType<DriverRuntimeParameters.TcpPortRangeTryCount>.Class, TcpPortRangeTryCount)
+            .BindSetEntry(GenericType<DriverRuntimeParameters.GlobalAssemblies>.Class, GlobalAssemblies)
+            .BindSetEntry(GenericType<DriverRuntimeParameters.LocalAssemblies>.Class, LocalAssemblies)
+            .BindSetEntry(GenericType<DriverRuntimeParameters.GlobalFiles>.Class, GlobalFiles)
+            .BindSetEntry(GenericType<DriverRuntimeParameters.LocalFiles>.Class, LocalFiles)
+            .Build();
+
+        /// <summary>
+        /// Add the assembly needed for the given Type to the driver.
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static ConfigurationModule AddLocalAssemblyForType(ConfigurationModule conf, Type type)
+        {
+            return conf.Set(LocalAssemblies, GetAssemblyPathForType(type));
+        }
+
+        /// <summary>
+        /// Add the assembly needed for the given Type to all containers.
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static ConfigurationModule AddGlobalAssemblyForType(ConfigurationModule conf, Type type)
+        {
+            return conf.Set(GlobalAssemblies, GetAssemblyPathForType(type));
+        }
+
+        /// <summary>
+        /// Finds the path to the assembly the given Type was loaded from.
+        /// </summary>
+        private static string GetAssemblyPathForType(Type type)
+        {
+            var path = Uri.UnescapeDataString(new UriBuilder(type.Assembly.CodeBase).Path);
+            return Path.GetFullPath(path);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverRuntimeParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverRuntimeParameters.cs
new file mode 100644
index 0000000..cb295ce
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/DriverRuntimeParameters.cs
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Tang.Annotations;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    public sealed class DriverRuntimeParameters
+    {
+        [NamedParameter("the job identifier")]
+        public sealed class JobId : Name<string>
+        {
+        }
+
+        [NamedParameter("The job submission directory", defaultValue: "")]
+        public sealed class JobSubmissionDirectory : Name<string>
+        {
+        }
+
+        [NamedParameter("Number of cpu cores", defaultValue: "1")]
+        public sealed class DriverCpuCores : Name<int>
+        {
+        }
+
+        [NamedParameter("The amount of driver memory in MB", defaultValue: "512")]
+        public sealed class DriverMemory : Name<int>
+        {
+        }
+
+        [NamedParameter("enable driver restart", defaultValue: "true")]
+        public sealed class EnableDriverRestart : Name<bool>
+        {
+        }
+
+        [NamedParameter("the amount of time to wait for evaluators to recover after failed driver", defaultValue: "0")]
+        public sealed class RestartEvaluatorRecoverySeconds : Name<int>
+        {
+        }
+
+        [NamedParameter("Driver and Evaluator assemblies.")]
+        public sealed class GlobalAssemblies : Name<ISet<string>>
+        {
+        }
+
+        [NamedParameter("Driver only related assemblies.")]
+        public sealed class LocalAssemblies : Name<ISet<string>>
+        {
+        }
+
+        [NamedParameter("Driver and Evaluator file resources.")]
+        public sealed class GlobalFiles : Name<ISet<string>>
+        {
+        }
+
+        [NamedParameter("Driver only related file resources.")]
+        public sealed class LocalFiles : Name<ISet<string>>
+        {
+        }
+
+        [NamedParameter("tcp port range begin", defaultValue: "0")]
+        public sealed class TcpPortRangeBegin : Name<int>
+        {
+        }
+
+        [NamedParameter("tcp port range count", defaultValue: "0")]
+        public sealed class TcpPortRangeCount : Name<int>
+        {
+        }
+
+        [NamedParameter("tcp port range try count", defaultValue: "0")]
+        public sealed class TcpPortRangeTryCount : Name<int>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/OsType.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/OsType.cs
new file mode 100644
index 0000000..3761da5
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/OsType.cs
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config
+{
+    [DefaultImplementation(typeof(OsWindows))]
+    public abstract class OsType
+    {
+        public enum Os
+        {
+            Windows, Linux
+        }
+
+        public abstract Os Type { get; }
+    }
+
+    public sealed class OsLinux : OsType
+    {
+        [Inject]
+        private OsLinux()
+        {
+        }
+
+        public override Os Type => Os.Linux;
+    }
+
+    public sealed class OsWindows : OsType
+    {
+        [Inject]
+        private OsWindows()
+        {
+        }
+
+        public override Os Type => Os.Windows;
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/AzureBatchRuntimeConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/AzureBatchRuntimeConfiguration.cs
new file mode 100644
index 0000000..cab65fb
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/AzureBatchRuntimeConfiguration.cs
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    public sealed class AzureBatchRuntimeConfiguration : ConfigurationModuleBuilder
+    {
+        private static readonly string AzBatchConfigurationFileEnvironmentVariable = "REEF_AZBATCH_CONF";
+
+        /// <summary>
+        /// The Azure Batch account URI.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureBatchAccountUri = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Batch account name.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureBatchAccountName = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Batch account key.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureBatchAccountKey = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Batch pool ID.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureBatchPoolId = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Storage account name.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureStorageAccountName = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Storage account key.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureStorageAccountKey = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Storage container name.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureStorageContainerName = new RequiredParameter<string>();
+
+        public static ConfigurationModule ConfigurationModule = new AzureBatchRuntimeConfiguration()
+            .BindImplementation(GenericType<IRuntimeProtoProvider>.Class, GenericType<AzureBatchRuntimeProtoProvider>.Class)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureBatchAccountUri>.Class,
+                AzureBatchAccountUri)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureBatchAccountName>.Class,
+                AzureBatchAccountName)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureBatchAccountKey>.Class,
+                AzureBatchAccountKey)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureBatchPoolId>.Class, AzureBatchPoolId)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureStorageAccountName>.Class,
+                AzureStorageAccountName)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureStorageAccountKey>.Class,
+                AzureStorageAccountKey)
+            .BindNamedParameter(GenericType<AzureBatchRuntimeParameters.AzureStorageContainerName>.Class,
+                AzureStorageContainerName)
+            .Build();
+
+        public static IConfiguration FromEnvironment()
+        {
+            return Utils.FromEnvironment(AzBatchConfigurationFileEnvironmentVariable);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/AzureBatchRuntimeParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/AzureBatchRuntimeParameters.cs
new file mode 100644
index 0000000..2dec1d4
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/AzureBatchRuntimeParameters.cs
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    internal sealed class AzureBatchRuntimeParameters
+    {
+        [NamedParameter(Documentation = "The Azure Batch Account Key")]
+        public sealed class AzureBatchAccountKey : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Batch Account Name")]
+        public sealed class AzureBatchAccountName : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Batch account URI")]
+        public sealed class AzureBatchAccountUri : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Batch Pool Id")]
+        public sealed class AzureBatchPoolId : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Storage Account Key")]
+        public sealed class AzureStorageAccountKey : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Storage Account Name")]
+        public sealed class AzureStorageAccountName : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Storage Container Name")]
+        public sealed class AzureStorageContainerName : Name<string>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/HdInsightRuntimeConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/HdInsightRuntimeConfiguration.cs
new file mode 100644
index 0000000..ce80559
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/HdInsightRuntimeConfiguration.cs
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    public sealed class HdInsightRuntimeConfiguration : ConfigurationModuleBuilder
+    {
+        private static readonly string HdiConfigurationFileEnvironmentVariable = "REEF_HDI_CONF";
+
+        /// <summary>
+        /// HDInsight URL.
+        /// </summary>
+        public static readonly RequiredParameter<string> HdInsightUrl = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The user name.
+        /// </summary>
+        public static readonly RequiredParameter<string> HdInsightUserName = new RequiredParameter<string>();
+
+        /// <summary>
+        /// Password.
+        /// </summary>
+        public static readonly RequiredParameter<string> HdInsightPassword = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Storage account name.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureStorageAccountName = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Storage account key.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureStorageAccountKey = new RequiredParameter<string>();
+
+        /// <summary>
+        /// The Azure Storage container name.
+        /// </summary>
+        public static readonly RequiredParameter<string> AzureStorageContainerName = new RequiredParameter<string>();
+
+        /// <summary>
+        /// Indicates whether to target an unsafe deployment.
+        /// </summary>
+        public static readonly OptionalParameter<bool> HdInsightUnsafeDeployment = new OptionalParameter<bool>();
+
+        public static ConfigurationModule ConfigurationModule = new HdInsightRuntimeConfiguration()
+            .BindImplementation(GenericType<IRuntimeProtoProvider>.Class, GenericType<HdInsightRuntimeProtoProvider>.Class)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.HdInsightUrl>.Class, HdInsightUrl)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.HdInsightUserName>.Class, HdInsightUserName)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.HdInsightPassword>.Class, HdInsightPassword)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.AzureStorageAccountName>.Class,
+                AzureStorageAccountName)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.AzureStorageAccountKey>.Class,
+                AzureStorageAccountKey)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.AzureStorageContainerName>.Class,
+                AzureStorageContainerName)
+            .BindNamedParameter(GenericType<HdInsightRuntimeParameters.HdInsightUnsafeDeployment>.Class, HdInsightUnsafeDeployment)
+            .Build();
+
+        public static IConfiguration FromEnvironment()
+        {
+            return Utils.FromEnvironment(HdiConfigurationFileEnvironmentVariable);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/HdInsightRuntimeParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/HdInsightRuntimeParameters.cs
new file mode 100644
index 0000000..190c96a
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/HdInsightRuntimeParameters.cs
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    internal sealed class HdInsightRuntimeParameters
+    {
+        [NamedParameter(Documentation = "Unsafe deployment of HDInsight", DefaultValue = "false")]
+        public sealed class HdInsightUnsafeDeployment : Name<bool>
+        {
+        }
+
+        [NamedParameter(Documentation = "HDInsight Password")]
+        public sealed class HdInsightPassword : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "HDInsight User Name")]
+        public sealed class HdInsightUserName : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "HDInsight URL")]
+        public sealed class HdInsightUrl : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Storage Account Key")]
+        public sealed class AzureStorageAccountKey : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Storage Account Name")]
+        public sealed class AzureStorageAccountName : Name<string>
+        {
+        }
+
+        [NamedParameter(Documentation = "The Azure Storage Container Name")]
+        public sealed class AzureStorageContainerName : Name<string>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/LocalRuntimeConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/LocalRuntimeConfiguration.cs
new file mode 100644
index 0000000..f0b086e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/LocalRuntimeConfiguration.cs
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Util;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    public sealed class LocalRuntimeConfiguration : ConfigurationModuleBuilder
+    {
+        /// <summary>
+        /// The number of threads or evaluators available to the resourcemanager.
+        /// </summary>
+        /// <remarks>
+        /// This is the upper limit on the number of
+        /// Evaluators that the local resourcemanager will hand out concurrently. This simulates the size of a physical cluster
+        /// in terms of the number of slots available on it with one important caveat: The Driver is not counted against this
+        /// number.
+        /// </remarks>
+        public static readonly OptionalParameter<int> NumberOfEvaluators = new OptionalParameter<int>();
+
+        /// <summary>
+        /// The folder in which the sub-folders, one per job, will be created.
+        /// </summary>
+        /// <remarks>
+        /// If none is given, the temp directory is used.
+        /// </remarks>
+        public static readonly OptionalParameter<string> RuntimeFolder = new OptionalParameter<string>();
+
+        public static ConfigurationModule ConfigurationModule = new LocalRuntimeConfiguration()
+            .BindImplementation(GenericType<IRuntimeProtoProvider>.Class, GenericType<LocalRuntimeProtoProvider>.Class)
+            .BindNamedParameter(GenericType<LocalRuntimeParameters.LocalRuntimeDirectory>.Class, RuntimeFolder)
+            .BindNamedParameter(GenericType<LocalRuntimeParameters.NumberOfEvaluators>.Class, NumberOfEvaluators)
+            .Build();
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/LocalRuntimeParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/LocalRuntimeParameters.cs
new file mode 100644
index 0000000..04af5fe
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/LocalRuntimeParameters.cs
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    internal sealed class LocalRuntimeParameters
+    {
+        [NamedParameter("The directory in which the local runtime will store its execution.", defaultValue: "")]
+        public class LocalRuntimeDirectory : Name<string>
+        {
+        }
+
+        [NamedParameter(defaultValue: "2")]
+        public class NumberOfEvaluators : Name<int>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/AzureBatchRuntimeProtoProvider.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/AzureBatchRuntimeProtoProvider.cs
new file mode 100644
index 0000000..73b6d4f
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/AzureBatchRuntimeProtoProvider.cs
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto
+{
+    internal sealed class AzureBatchRuntimeProtoProvider : IRuntimeProtoProvider
+    {
+        private readonly Core.Proto.AzureBatchRuntimeParameters _azureBatchRuntimeParameters;
+
+        [Inject]
+        private AzureBatchRuntimeProtoProvider(
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureBatchAccountKey))] string accountKey,
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureBatchAccountName))] string accountName,
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureBatchAccountUri))] string accountUri,
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureBatchPoolId))] string poolId,
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureStorageAccountKey))] string storageAccountKey,
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureStorageAccountName))] string storageAccountName,
+            [Parameter(Value = typeof(AzureBatchRuntimeParameters.AzureStorageContainerName))] string storageContainerName)
+        {
+            _azureBatchRuntimeParameters = new Core.Proto.AzureBatchRuntimeParameters()
+            {
+                AzureBatchAccountKey = accountKey,
+                AzureBatchAccountName = accountName,
+                AzureBatchAccountUri = accountUri,
+                AzureBatchPoolId = poolId,
+                AzureStorageAccountKey = storageAccountKey,
+                AzureStorageAccountName = storageAccountName,
+                AzureStorageContainerName = storageContainerName
+            };
+        }
+
+        public void SetParameters(DriverClientConfiguration driverClientConfiguration)
+        {
+            driverClientConfiguration.AzbatchRuntime = _azureBatchRuntimeParameters;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/HdInsightRuntimeProtoProvider.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/HdInsightRuntimeProtoProvider.cs
new file mode 100644
index 0000000..7fb259f
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/HdInsightRuntimeProtoProvider.cs
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto
+{
+    internal sealed class HdInsightRuntimeProtoProvider : IRuntimeProtoProvider
+    {
+        private readonly HDIRuntimeParameters _hdiRuntimeParameters;
+
+        [Inject]
+        private HdInsightRuntimeProtoProvider(
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.HdInsightUnsafeDeployment))] bool unsafeDeplyment,
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.HdInsightUserName))] string userName,
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.HdInsightPassword))] string password,
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.HdInsightUrl))] string url,
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.AzureStorageAccountKey))] string storageAccountKey,
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.AzureStorageAccountName))] string storageAccountName,
+            [Parameter(Value = typeof(HdInsightRuntimeParameters.AzureStorageContainerName))] string storageContainerName)
+        {
+            _hdiRuntimeParameters = new HDIRuntimeParameters()
+            {
+                Unsafe = unsafeDeplyment,
+                HdiUserName = userName,
+                HdiPassword = password,
+                HdiUrl = url,
+                AzureStorageAccountKey = storageAccountKey,
+                AzureStorageAccountName = storageAccountName,
+                AzureStorageContainerName = storageContainerName
+            };
+        }
+
+        public void SetParameters(DriverClientConfiguration driverClientConfiguration)
+        {
+            driverClientConfiguration.HdiRuntime = _hdiRuntimeParameters;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/IRuntimeProtoProvider.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/IRuntimeProtoProvider.cs
new file mode 100644
index 0000000..334f3ea
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/IRuntimeProtoProvider.cs
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Proto;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto
+{
+    internal interface IRuntimeProtoProvider
+    {
+        void SetParameters(DriverClientConfiguration driverClientConfiguration);
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/LocalRuntimeProtoProvider.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/LocalRuntimeProtoProvider.cs
new file mode 100644
index 0000000..5dc212f
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/LocalRuntimeProtoProvider.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto
+{
+    internal sealed class LocalRuntimeProtoProvider : IRuntimeProtoProvider
+    {
+        private readonly Core.Proto.LocalRuntimeParameters _localRuntimeParameters;
+
+        [Inject]
+        private LocalRuntimeProtoProvider(
+            [Parameter(Value = typeof(LocalRuntimeParameters.LocalRuntimeDirectory))] string localRuntimeDirectory,
+            [Parameter(Value = typeof(LocalRuntimeParameters.NumberOfEvaluators))] int numberOfEvaluators)
+        {
+            if (numberOfEvaluators <= 0)
+            {
+                throw new IllegalStateException("Number of evaluators must be greater than zero");
+            }
+            _localRuntimeParameters = new Core.Proto.LocalRuntimeParameters()
+            {
+                MaxNumberOfEvaluators = (uint)numberOfEvaluators,
+                RuntimeRootFolder = localRuntimeDirectory
+            };
+        }
+
+        public void SetParameters(DriverClientConfiguration driverClientConfiguration)
+        {
+            driverClientConfiguration.LocalRuntime = _localRuntimeParameters;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/YarnRuntimeProtoProvider.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/YarnRuntimeProtoProvider.cs
new file mode 100644
index 0000000..0b9adad
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Proto/YarnRuntimeProtoProvider.cs
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto
+{
+    internal sealed class YarnRuntimeProtoProvider : IRuntimeProtoProvider
+    {
+        private readonly Core.Proto.YarnRuntimeParameters _yarnRuntimeParameters;
+
+        [Inject]
+        private YarnRuntimeProtoProvider(
+            [Parameter(Value = typeof(YarnRuntimeParameters.JobPriority))] int jobPriority,
+            [Parameter(Value = typeof(YarnRuntimeParameters.JobQueue))] string jobQueue,
+            [Parameter(Value = typeof(YarnRuntimeParameters.JobSubmissionDirectoryPrefix))] string jobSubmissionDirectoryPrefix,
+            [Parameter(Value = typeof(YarnRuntimeParameters.SecurityTokenStrings))] ISet<string> securityTokenStrings,
+            [Parameter(Value = typeof(YarnRuntimeParameters.UnmanagedDriver))] bool unmanagedDriver,
+            [Parameter(Value = typeof(YarnRuntimeParameters.FileSystemUrl))] string fileSystemUrl)
+        {
+            if (jobPriority < 0)
+            {
+                throw new IllegalStateException("Job Priority must be greater than or equal to zero");
+            }
+            _yarnRuntimeParameters = new Core.Proto.YarnRuntimeParameters()
+            {
+                Priority = (uint)jobPriority,
+                Queue = jobQueue,
+                JobSubmissionDirectoryPrefix = jobSubmissionDirectoryPrefix,
+                UnmangedDriver = unmanagedDriver,
+                FilesystemUrl = fileSystemUrl
+            };
+        }
+
+        public void SetParameters(DriverClientConfiguration driverClientConfiguration)
+        {
+            driverClientConfiguration.YarnRuntime = _yarnRuntimeParameters;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Utils.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Utils.cs
new file mode 100644
index 0000000..1935f33
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/Utils.cs
@@ -0,0 +1,47 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Interface;
+using System;
+using System.IO;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    internal static class Utils
+    {
+        public static IConfiguration FromTextFile(string file)
+        {
+            return new AvroConfigurationSerializer().FromFile(file);
+        }
+
+        public static IConfiguration FromEnvironment(string environmentVariable)
+        {
+            var configurationPath = Environment.GetEnvironmentVariable(environmentVariable);
+            if (configurationPath == null)
+            {
+                throw new ArgumentException($"Environment Variable {environmentVariable} not set");
+            }
+
+            if (!File.Exists(configurationPath))
+            {
+                throw new ArgumentException($"File located by Environment Variable {environmentVariable} cannot be read.");
+            }
+            return FromTextFile(configurationPath);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/YarnRuntimeConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/YarnRuntimeConfiguration.cs
new file mode 100644
index 0000000..53e5acd
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/YarnRuntimeConfiguration.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Util;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    public sealed class YarnRuntimeConfiguration : ConfigurationModuleBuilder
+    {
+        public static readonly OptionalParameter<int> JobPriority = new OptionalParameter<int>();
+        public static readonly OptionalParameter<string> JobQueue = new OptionalParameter<string>();
+        public static readonly OptionalParameter<string> JobSubmissionDirectoryPrefix = new OptionalParameter<string>();
+        public static readonly OptionalParameter<string> SecurityTokenStrings = new OptionalParameter<string>();
+        public static readonly OptionalParameter<bool> UnmanagedDriver = new OptionalParameter<bool>();
+
+        /// <summary>
+        /// URL for store. For Hadoop file system, it is set in fs.defaultFS as default by YARN environment. Client doesn't need to
+        /// specify it. For Data Lake, Yarn applications are required to set the complete path by themselves
+        /// e.g. adl://reefadl.azuredatalakestore.net
+        /// </summary>
+        public static readonly OptionalParameter<string> FileSystemUrl = new OptionalParameter<string>();
+
+        public static ConfigurationModule ConfigurationModule = new YarnRuntimeConfiguration()
+            .BindImplementation(GenericType<IRuntimeProtoProvider>.Class, GenericType<YarnRuntimeProtoProvider>.Class)
+            .BindNamedParameter(GenericType<YarnRuntimeParameters.JobPriority>.Class, JobPriority)
+            .BindNamedParameter(GenericType<YarnRuntimeParameters.JobSubmissionDirectoryPrefix>.Class, JobSubmissionDirectoryPrefix)
+            .BindNamedParameter(GenericType<YarnRuntimeParameters.JobQueue>.Class, JobQueue)
+            .BindSetEntry(GenericType<YarnRuntimeParameters.SecurityTokenStrings>.Class, SecurityTokenStrings)
+            .BindNamedParameter(GenericType<YarnRuntimeParameters.FileSystemUrl>.Class, FileSystemUrl)
+            .BindNamedParameter(GenericType<YarnRuntimeParameters.UnmanagedDriver>.Class, UnmanagedDriver)
+            .Build();
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/YarnRuntimeParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/YarnRuntimeParameters.cs
new file mode 100644
index 0000000..048c1bb
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Config/Runtime/YarnRuntimeParameters.cs
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Tang.Annotations;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime
+{
+    internal sealed class YarnRuntimeParameters
+    {
+        [NamedParameter("FileSystem URL.", defaultValue: "")]
+        public sealed class FileSystemUrl : Name<string>
+        {
+        }
+
+        [NamedParameter("The job priority", defaultValue: "0")]
+        public sealed class JobPriority : Name<int>
+        {
+        }
+
+        [NamedParameter("The job queue.", defaultValue: "")]
+        public sealed class JobQueue : Name<string>
+        {
+        }
+
+        [NamedParameter("Directory used to upload job resources from the client", defaultValue: @"/vol1/tmp")]
+        public class JobSubmissionDirectoryPrefix : Name<string>
+        {
+        }
+
+        /// <summary>
+        /// Named parameter that contains a set of serialized tokens.
+        /// </summary>
+        [NamedParameter("Serialized SurityToken Info", defaultValue: "")]
+        public class SecurityTokenStrings : Name<ISet<string>>
+        {
+        }
+
+        [NamedParameter("Boolean indicating whether we want an unmanged driver.", defaultValue: "false")]
+        public sealed class UnmanagedDriver : Name<bool>
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultCompletedJobHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultCompletedJobHandler.cs
new file mode 100644
index 0000000..1dc5d3c
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultCompletedJobHandler.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultCompletedJobHandler : IObserver<ICompletedJob>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultCompletedJobHandler));
+
+        [Inject]
+        private DefaultCompletedJobHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(ICompletedJob value)
+        {
+            Log.Log(Level.Info, "Job {0} completed", value.Id);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultFailedJobHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultFailedJobHandler.cs
new file mode 100644
index 0000000..db71898
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultFailedJobHandler.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultFailedJobHandler : IObserver<IFailedJob>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultFailedJobHandler));
+
+        [Inject]
+        private DefaultFailedJobHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(IFailedJob value)
+        {
+            Log.Log(Level.Error, $"Job {value.Id} failed", value.AsError());
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultFailedRuntimeHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultFailedRuntimeHandler.cs
new file mode 100644
index 0000000..f4ccfd3
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultFailedRuntimeHandler.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultFailedRuntimeHandler : IObserver<IFailedRuntime>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultFailedRuntimeHandler));
+
+        [Inject]
+        private DefaultFailedRuntimeHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(IFailedRuntime value)
+        {
+            Log.Log(Level.Error, $"Job {value.Id} runtime failure", value.AsError());
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultJobMessageHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultJobMessageHandler.cs
new file mode 100644
index 0000000..19d80e9
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultJobMessageHandler.cs
@@ -0,0 +1,61 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultJobMessageHandler : IObserver<IJobMessage>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultJobMessageHandler));
+
+        [Inject]
+        private DefaultJobMessageHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(IJobMessage value)
+        {
+            var message = "unable to deserialize message";
+            try
+            {
+                message = ByteUtilities.ByteArraysToString(value.Message);
+            }
+            catch (SerializationException)
+            {
+                var opaque = ByteUtilities.DeserializeFromBinaryFormat(value.Message);
+                message = opaque.ToString();
+            }
+            Log.Log(Level.Info, "Job {0} sent message {1}", value.Id, message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultRunningJobHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultRunningJobHandler.cs
new file mode 100644
index 0000000..2e35da6
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultRunningJobHandler.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultRunningJobHandler : IObserver<IRunningJob>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultRunningJobHandler));
+
+        [Inject]
+        private DefaultRunningJobHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(IRunningJob value)
+        {
+            Log.Log(Level.Info, "Job {0} is running", value.Id);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultSubmittedJobHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultSubmittedJobHandler.cs
new file mode 100644
index 0000000..4a919e4
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultSubmittedJobHandler.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultSubmittedJobHandler : IObserver<ISubmittedJob>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultSubmittedJobHandler));
+
+        [Inject]
+        private DefaultSubmittedJobHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(ISubmittedJob value)
+        {
+            Log.Log(Level.Info, "Job {0} submitted", value.Id);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultWakeErrorHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultWakeErrorHandler.cs
new file mode 100644
index 0000000..95ba1fa
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Default/DefaultWakeErrorHandler.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Default
+{
+    internal sealed class DefaultWakeErrorHandler : IObserver<IWakeError>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultWakeErrorHandler));
+
+        [Inject]
+        private DefaultWakeErrorHandler()
+        {
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(IWakeError value)
+        {
+            Log.Log(Level.Error, $"Job {value.Id} wake error", value.AsError());
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/CompletedJob.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/CompletedJob.cs
new file mode 100644
index 0000000..92b2a58
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/CompletedJob.cs
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class CompletedJob : ICompletedJob
+    {
+        public CompletedJob(string id)
+        {
+            Id = id;
+        }
+
+        public string Id { get; }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/FailedJob.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/FailedJob.cs
new file mode 100644
index 0000000..55214a2
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/FailedJob.cs
@@ -0,0 +1,64 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Utilities;
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class FailedJob : IFailedJob
+    {
+        public FailedJob(string jobId, string message, byte[] data = null)
+        {
+            Id = jobId;
+            Message = message;
+            Data = Optional<byte[]>.OfNullable(data);
+        }
+
+        public string Id { get; }
+        public string Message { get; set; }
+        public Optional<string> Description { get; set; }
+        public Optional<string> Reason { get; set; }
+        public Optional<byte[]> Data { get; set; }
+
+        public Exception AsError()
+        {
+            if (Data.IsPresent())
+            {
+                Exception inner;
+                try
+                {
+                    inner = (Exception)ByteUtilities.DeserializeFromBinaryFormat(Data.Value);
+                }
+                catch (SerializationException se)
+                {
+                    inner = NonSerializableEvaluatorException.UnableToDeserialize(
+                        "Not able to deserialize job exception.",
+                        se);
+                }
+                return new JobException(Id, Message, inner);
+            }
+            else
+            {
+                return new JobException(Id, Message);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/FailedRuntime.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/FailedRuntime.cs
new file mode 100644
index 0000000..3c09ce7
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/FailedRuntime.cs
@@ -0,0 +1,64 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Utilities;
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class FailedRuntime : IFailedRuntime
+    {
+        public string Id { get; }
+        public string Message { get; set; }
+        public Optional<string> Description { get; set; }
+        public Optional<string> Reason { get; set; }
+        public Optional<byte[]> Data { get; set; }
+
+        public FailedRuntime(string id, string message, byte[] data = null)
+        {
+            Id = id;
+            Message = message;
+            Data = Optional<byte[]>.OfNullable(data);
+        }
+
+        public Exception AsError()
+        {
+            if (Data.IsPresent())
+            {
+                Exception inner;
+                try
+                {
+                    inner = (Exception)ByteUtilities.DeserializeFromBinaryFormat(Data.Value);
+                }
+                catch (SerializationException se)
+                {
+                    inner = NonSerializableEvaluatorException.UnableToDeserialize(
+                        "Exception from Evaluator was not able to be deserialized, returning a NonSerializableEvaluatorException.",
+                        se);
+                }
+                return new JobException(Id, Message, inner);
+            }
+            else
+            {
+                return new JobException(Id, Message);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/JobMessage.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/JobMessage.cs
new file mode 100644
index 0000000..d922edb
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/JobMessage.cs
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class JobMessage : IJobMessage
+    {
+        public JobMessage(string id, byte[] message)
+        {
+            Id = id;
+            Message = message;
+        }
+
+        public string Id { get; }
+        public byte[] Message { get; }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/RunningJob.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/RunningJob.cs
new file mode 100644
index 0000000..c4934a4
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/RunningJob.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class RunningJob : IRunningJob
+    {
+        private readonly IClientService _clientService;
+
+        public RunningJob(IClientService clientService, string jobId)
+        {
+            _clientService = clientService;
+            Id = jobId;
+        }
+
+        public string Id { get; }
+
+        public void Dispose()
+        {
+            _clientService.Close();
+        }
+
+        public void Dispose(byte[] message)
+        {
+            _clientService.Close(message);
+        }
+
+        public void Send(byte[] message)
+        {
+            _clientService.Send(message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/SubmittedJob.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/SubmittedJob.cs
new file mode 100644
index 0000000..36c106b
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/SubmittedJob.cs
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class SubmittedJob : ISubmittedJob
+    {
+        public string Id { get; }
+
+        public SubmittedJob(string jobId)
+        {
+            Id = jobId;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/WakeError.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/WakeError.cs
new file mode 100644
index 0000000..0ba47d9
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/Events/WakeError.cs
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Utilities;
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client.Events
+{
+    internal sealed class WakeError : IWakeError
+    {
+        public WakeError(string id, string message) : this(id, message, Optional<byte[]>.Empty())
+        {
+        }
+
+        public WakeError(string id, string message, Optional<byte[]> data)
+        {
+            Id = id;
+            Message = message;
+            Data = data;
+        }
+
+        public string Id { get; }
+        public string Message { get; set; }
+        public Optional<string> Description { get; set; }
+        public Optional<string> Reason { get; set; }
+        public Optional<byte[]> Data { get; set; }
+
+        public Exception AsError()
+        {
+            if (Data.IsPresent())
+            {
+                Exception inner;
+                try
+                {
+                    inner = (Exception)ByteUtilities.DeserializeFromBinaryFormat(Data.Value);
+                }
+                catch (SerializationException se)
+                {
+                    inner = NonSerializableEvaluatorException.UnableToDeserialize(
+                        "Exception from Evaluator was not able to be deserialized, returning a NonSerializableEvaluatorException.",
+                        se);
+                }
+                return new JobException(Id, Message, inner);
+            }
+            else
+            {
+                return new JobException(Id, Message);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/IClientLauncher.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/IClientLauncher.cs
new file mode 100644
index 0000000..ff2b7f2
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/IClientLauncher.cs
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Interface;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client
+{
+    /// <inheritdoc />
+    /// <summary>
+    /// All client launchers implement this interface. Multiple jobs can be submitted until the
+    /// launcher has been disposed <see cref="T:System.IDisposable" />
+    /// </summary>
+    public interface IClientLauncher : IDisposable
+    {
+        Task<LauncherStatus> SubmitAsync(
+            IConfiguration driverAppConfiguration,
+            CancellationToken cancellationToken = default);
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/IClientService.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/IClientService.cs
new file mode 100644
index 0000000..ecaa80d
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/IClientService.cs
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client
+{
+    /// <summary>
+    /// Interface that all client services implement that provide
+    /// control flow channels to the driver.
+    /// </summary>
+    internal interface IClientService
+    {
+        /// <summary>
+        /// Shutdown the job with an optional message.
+        /// </summary>
+        /// <param name="message">to deliver to the driver</param>
+        void Close(byte[] message = null);
+
+        /// <summary>
+        /// Send the driver a message.
+        /// </summary>
+        /// <param name="message">to deliver to the driver</param>
+        void Send(byte[] message);
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/JavaClientLauncher.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/JavaClientLauncher.cs
new file mode 100644
index 0000000..1c75d74
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Client/JavaClientLauncher.cs
@@ -0,0 +1,185 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Client
+{
+    /// <summary>
+    /// Helper class to launch the java side of the various clients.
+    /// </summary>
+    internal sealed class JavaClientLauncher
+    {
+        /// <summary>
+        /// The folder in which we search for the client jar.
+        /// </summary>
+        private const string JarFolder = "./";
+
+        private static readonly Logger Log = Logger.GetLogger(typeof(JavaClientLauncher));
+
+        [Inject]
+        private JavaClientLauncher()
+        {
+        }
+
+        /// <summary>
+        /// Launch a java class in ClientConstants.ClientJarFilePrefix with provided parameters.
+        /// </summary>
+        /// <param name="javaLogLevel">Java logging level</param>
+        /// <param name="javaClassName">Java class that launches the Java driver</param>
+        /// <param name="parameters">Parameters associated with the Java main class</param>
+        /// <param name="cancellationToken">Token to cancel the launch</param>
+        public Task LaunchAsync(
+            JavaLoggingSetting javaLogLevel,
+            string javaClassName,
+            string[] parameters,
+            CancellationToken cancellationToken = default)
+        {
+            var startInfo = new ProcessStartInfo
+            {
+                Arguments = AssembleArguments(javaLogLevel, javaClassName, parameters),
+                FileName = GetJavaCommand(),
+                UseShellExecute = false,
+                RedirectStandardOutput = true,
+                RedirectStandardError = true,
+            };
+            Log.Log(Level.Info, "Launch Java with command: {0} {1}", startInfo.FileName, startInfo.Arguments);
+            var processExitTracker = new TaskCompletionSource<bool>();
+            var process = new Process
+            {
+                StartInfo = startInfo,
+                EnableRaisingEvents = true
+            };
+            process.Exited += (sender, args) => { processExitTracker.SetResult(process.ExitCode == 0); };
+            if (cancellationToken != default)
+            {
+                cancellationToken.Register(processExitTracker.SetCanceled);
+            }
+            process.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e)
+            {
+                if (!string.IsNullOrWhiteSpace(e.Data))
+                {
+                    Log.Log(Level.Info, e.Data);
+                }
+            };
+            process.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e)
+            {
+                if (!string.IsNullOrWhiteSpace(e.Data))
+                {
+                    Log.Log(Level.Error, e.Data);
+                }
+            };
+            if (!process.Start())
+            {
+                processExitTracker.SetException(new Exception("Java client process didn't start."));
+            }
+            else
+            {
+                process.BeginErrorReadLine();
+                process.BeginOutputReadLine();
+            }
+            return processExitTracker.Task;
+        }
+
+        /// <summary>
+        /// Assembles the command line arguments. Used by LaunchAsync()
+        /// </summary>
+        /// <param name="javaLogLevel"></param>
+        /// <param name="javaClassName"></param>
+        /// <param name="parameters"></param>
+        /// <returns></returns>
+        private string AssembleArguments(JavaLoggingSetting javaLogLevel, string javaClassName, params string[] parameters)
+        {
+            IList<string> arguments = new List<string>();
+
+            if (javaLogLevel == JavaLoggingSetting.Verbose)
+            {
+                arguments.Add("-Djava.util.logging.config.class=org.apache.reef.util.logging.Config");
+            }
+
+            arguments.Add("-cp");
+            arguments.Add(GetClientClasspath());
+            arguments.Add(javaClassName);
+            return string.Join(" ", arguments.Concat(parameters));
+        }
+
+        /// <summary>
+        /// Find the `java` command on this machine and returns its path.
+        /// </summary>
+        /// <exception cref="JavaNotFoundException">If the java binary couldn't be found.</exception>
+        /// <returns>The path of the `java` command on this machine.</returns>
+        private static string GetJavaCommand()
+        {
+            var javaHomePath = Environment.GetEnvironmentVariable("JAVA_HOME");
+            if (string.IsNullOrWhiteSpace(javaHomePath))
+            {
+                // TODO: Attempt to find java via the registry.
+                throw new IllegalStateException("JAVA_HOME isn't set. Please install Java and make set JAVA_HOME");
+            }
+
+            if (!Directory.Exists(javaHomePath))
+            {
+                throw new IllegalStateException($"JAVA_HOME references a folder that doesn\'t exist. {javaHomePath}");
+            }
+
+            var javaBinPath = Path.Combine(javaHomePath, "bin");
+            if (!Directory.Exists(javaBinPath))
+            {
+                throw new IllegalStateException(
+                    $"JAVA_HOME references a folder that doesn\'t contain a `bin` folder. Please adjust JAVA_HOME {javaHomePath}");
+            }
+
+            var javaPath = Path.Combine(javaBinPath, "java.exe");
+            if (File.Exists(javaPath)) return javaPath;
+            javaPath = Path.Combine(javaBinPath, "java");
+            if (!File.Exists(javaPath))
+            {
+                throw new IllegalStateException(
+                    "Could not find java executable on this machine. Is Java installed and JAVA_HOME set? " + javaBinPath);
+            }
+            return javaPath;
+        }
+
+        /// <summary>
+        /// Assembles the classpath for the side process
+        /// </summary>
+        /// <exception cref="ClasspathException">If the classpath would be empty.</exception>
+        /// <returns></returns>
+        private static string GetClientClasspath()
+        {
+            var files = Directory.GetFiles(JarFolder)
+                .Where(e => Path.GetFileName(e).ToLower().Contains("reef-bridge-proto-java"))
+                .ToList();
+            if (files.Count == 0)
+            {
+                throw new IllegalStateException(
+                    "Unable to assemble classpath. Make sure the REEF Jar is in the current working directory.");
+            }
+            return string.Join(";", files);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/BridgeClock.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/BridgeClock.cs
new file mode 100644
index 0000000..227b186
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/BridgeClock.cs
@@ -0,0 +1,119 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Implementations.InjectionPlan;
+using Org.Apache.REEF.Utilities.Logging;
+using Org.Apache.REEF.Wake.Time;
+using Org.Apache.REEF.Wake.Time.Event;
+using Org.Apache.REEF.Wake.Time.Runtime.Event;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    internal sealed class BridgeClock : IClock
+    {
+        internal struct AlarmInfo
+        {
+            public string AlarmId { get; set; }
+
+            public long Timestamp { get; set; }
+        }
+
+        private static readonly Logger Log = Logger.GetLogger(typeof(BridgeClock));
+
+        private readonly IInjectionFuture<IDriverServiceClient> _driverServiceClient;
+
+        private readonly IInjectionFuture<IDriverClientService> _driverClientService;
+
+        private readonly IDictionary<string, IObserver<Alarm>> _alarmDictionary = new Dictionary<string, IObserver<Alarm>>();
+
+        private int _outstandingAlarms;
+
+        [Inject]
+        private BridgeClock(
+            IInjectionFuture<IDriverServiceClient> driverServiceClient,
+            IInjectionFuture<IDriverClientService> driverClientService)
+        {
+            _driverServiceClient = driverServiceClient;
+            _driverClientService = driverClientService;
+            _outstandingAlarms = 0;
+        }
+
+        public void Dispose()
+        {
+            _driverServiceClient.Get().OnShutdown();
+        }
+
+        public void Dispose(Exception ex)
+        {
+            _driverServiceClient.Get().OnShutdown(ex);
+        }
+
+        public bool IsIdle()
+        {
+            return _outstandingAlarms == 0 && _alarmDictionary.Count == 0;
+        }
+
+        public void ScheduleAlarm(long offset, IObserver<Alarm> handler)
+        {
+            var alarmId = Guid.NewGuid().ToString();
+            _alarmDictionary[alarmId] = handler;
+            Log.Log(Level.Info, "Schedule alarm id {0} for {1}", alarmId, offset);
+            _driverServiceClient.Get().OnSetAlarm(alarmId, offset);
+        }
+
+        public void Run()
+        {
+            _driverClientService.Get().Start();
+            _driverClientService.Get().AwaitTermination();
+            Log.Log(Level.Info, "bridge clock terminated");
+        }
+
+        public void OnNext(AlarmInfo alarmInfo)
+        {
+            OnNextAsync(alarmInfo).GetAwaiter().GetResult();
+        }
+
+        public async Task OnNextAsync(AlarmInfo alarmInfo)
+        {
+            Log.Log(Level.Info, "scheduling alarm id {0}", alarmInfo.AlarmId);
+            if (_alarmDictionary.TryGetValue(alarmInfo.AlarmId, out IObserver<Alarm> alarmObserver))
+            {
+                Interlocked.Increment(ref _outstandingAlarms);
+                try
+                {
+                    var alarm = new RuntimeAlarm(alarmInfo.Timestamp, alarmObserver);
+                    _alarmDictionary.Remove(alarmInfo.AlarmId);
+                    await Task.Run(() => alarm.Handle());
+                }
+                catch (Exception ex)
+                {
+                    Log.Log(Level.Error, "Alarm handler raised exception", ex);
+                    Dispose(ex);
+                }
+                finally
+                {
+                    Interlocked.Decrement(ref _outstandingAlarms);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DispatchEventHandler.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DispatchEventHandler.cs
new file mode 100644
index 0000000..a7f9367
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DispatchEventHandler.cs
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    internal sealed class DispatchEventHandler<T> : IObserver<T>, IObservable<T>
+    {
+        private readonly ISet<IObserver<T>> _userHandlers;
+
+        public DispatchEventHandler()
+        {
+            _userHandlers = new HashSet<IObserver<T>>();
+        }
+
+        public DispatchEventHandler(ISet<IObserver<T>> userHandlers)
+        {
+            _userHandlers = userHandlers;
+        }
+
+        public void OnNext(T value)
+        {
+            foreach (var observer in _userHandlers)
+            {
+                observer.OnNext(value);
+            }
+        }
+
+        public void OnError(Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public IDisposable Subscribe(IObserver<T> observer)
+        {
+            _userHandlers.Add(observer);
+            return new DisposeImpl()
+            {
+                DispatchEventHandler = this,
+                Handler = observer
+            };
+        }
+
+        private class DisposeImpl : IDisposable
+        {
+            public DispatchEventHandler<T> DispatchEventHandler { private get; set; }
+            public IObserver<T> Handler { private get; set; }
+
+            public void Dispose()
+            {
+                DispatchEventHandler._userHandlers.Remove(Handler);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridge.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridge.cs
new file mode 100644
index 0000000..d6db5c8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridge.cs
@@ -0,0 +1,353 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config;
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    /// <summary>
+    /// DriverBridge is responsible for running application handlers and keeping
+    /// track of how many are currently active. It exposes a method <see cref="IsIdle"/>
+    /// that indicates if there are any active handlers, which is used to determine
+    /// (among other things) whether the driver is currently idle.
+    /// </summary>
+    internal sealed class DriverBridge
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DriverBridge));
+
+        // Control event dispatchers
+
+        private readonly DispatchEventHandler<IDriverStarted> _driverStartedDispatcher;
+
+        private readonly DispatchEventHandler<IDriverStopped> _driverStoppedDispatcher;
+
+        // Evaluator event dispatchers
+
+        private readonly DispatchEventHandler<IAllocatedEvaluator> _allocatedEvaluatorDispatcher;
+
+        private readonly DispatchEventHandler<IFailedEvaluator> _failedEvaluatorDispatcher;
+
+        private readonly DispatchEventHandler<ICompletedEvaluator> _completedEvaluatorDispatcher;
+
+        // Context event dispatchers
+
+        private readonly DispatchEventHandler<IActiveContext> _activeContextDispatcher;
+
+        private readonly DispatchEventHandler<IClosedContext> _closedContextDispatcher;
+
+        private readonly DispatchEventHandler<IFailedContext> _failedContextDispatcher;
+
+        private readonly DispatchEventHandler<IContextMessage> _contextMessageDispatcher;
+
+        // Task event dispatchers
+
+        private readonly DispatchEventHandler<ITaskMessage> _taskMessageDispatcher;
+
+        private readonly DispatchEventHandler<IFailedTask> _failedTaskDispatcher;
+
+        private readonly DispatchEventHandler<IRunningTask> _runningTaskDispatcher;
+
+        private readonly DispatchEventHandler<ICompletedTask> _completedTaskDispatcher;
+
+        private readonly DispatchEventHandler<ISuspendedTask> _suspendedTaskDispatcher;
+
+        // Driver restart event dispatchers
+
+        private readonly DispatchEventHandler<IDriverRestarted> _driverRestartedDispatcher;
+
+        private readonly DispatchEventHandler<IActiveContext> _driverRestartActiveContextDispatcher;
+
+        private readonly DispatchEventHandler<IRunningTask> _driverRestartRunningTaskDispatcher;
+
+        private readonly DispatchEventHandler<IDriverRestartCompleted> _driverRestartCompletedDispatcher;
+
+        private readonly DispatchEventHandler<IFailedEvaluator> _driverRestartFailedEvaluatorDispatcher;
+
+        // Client event handlers
+
+        private readonly DispatchEventHandler<byte[]> _clientCloseDispatcher;
+
+        private readonly DispatchEventHandler<byte[]> _clientCloseWithMessageDispatcher;
+
+        private readonly DispatchEventHandler<byte[]> _clientMessageDispatcher;
+
+        private static int s_activeDispatchCounter;
+
+        public static bool IsIdle => s_activeDispatchCounter == 0;
+
+        [Inject]
+        private DriverBridge(
+            // Runtime events
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverStartedHandlers))]
+            ISet<IObserver<IDriverStarted>> driverStartHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverStopHandlers))]
+            ISet<IObserver<IDriverStopped>> driverStopHandlers,
+            // Evaluator events
+            [Parameter(Value = typeof(DriverApplicationParameters.AllocatedEvaluatorHandlers))]
+            ISet<IObserver<IAllocatedEvaluator>> allocatedEvaluatorHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.FailedEvaluatorHandlers))]
+            ISet<IObserver<IFailedEvaluator>> failedEvaluatorHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.CompletedEvaluatorHandlers))]
+            ISet<IObserver<ICompletedEvaluator>> completedEvaluatorHandlers,
+            // Context events
+            [Parameter(Value = typeof(DriverApplicationParameters.ActiveContextHandlers))]
+            ISet<IObserver<IActiveContext>> activeContextHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.ClosedContextHandlers))]
+            ISet<IObserver<IClosedContext>> closedContextHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.FailedContextHandlers))]
+            ISet<IObserver<IFailedContext>> failedContextHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.ContextMessageHandlers))]
+            ISet<IObserver<IContextMessage>> contextMessageHandlers,
+            // Task events
+            [Parameter(Value = typeof(DriverApplicationParameters.TaskMessageHandlers))]
+            ISet<IObserver<ITaskMessage>> taskMessageHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.FailedTaskHandlers))]
+            ISet<IObserver<IFailedTask>> failedTaskHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.RunningTaskHandlers))]
+            ISet<IObserver<IRunningTask>> runningTaskHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.CompletedTaskHandlers))]
+            ISet<IObserver<ICompletedTask>> completedTaskHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.SuspendedTaskHandlers))]
+            ISet<IObserver<ISuspendedTask>> suspendedTaskHandlers,
+            // Driver restart events
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverRestartedHandlers))]
+            ISet<IObserver<IDriverRestarted>> driverRestartedHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverRestartActiveContextHandlers))]
+            ISet<IObserver<IActiveContext>> driverRestartActiveContextHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverRestartRunningTaskHandlers))]
+            ISet<IObserver<IRunningTask>> driverRestartRunningTaskHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverRestartCompletedHandlers))]
+            ISet<IObserver<IDriverRestartCompleted>> driverRestartCompletedHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.DriverRestartFailedEvaluatorHandlers))]
+            ISet<IObserver<IFailedEvaluator>> driverRestartFailedEvaluatorHandlers,
+            // Client event
+            [Parameter(Value = typeof(DriverApplicationParameters.ClientCloseWithMessageHandlers))]
+            ISet<IObserver<byte[]>> clientCloseWithMessageHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.ClientCloseHandlers))]
+            ISet<IObserver<byte[]>> clientCloseHandlers,
+            [Parameter(Value = typeof(DriverApplicationParameters.ClientMessageHandlers))]
+            ISet<IObserver<byte[]>> clientMessageHandlers,
+            // Misc.
+            [Parameter(Value = typeof(DriverApplicationParameters.TraceListeners))]
+            ISet<TraceListener> traceListeners,
+            [Parameter(Value = typeof(DriverApplicationParameters.TraceLevel))]
+            string traceLevel)
+        {
+            _driverStartedDispatcher = new DispatchEventHandler<IDriverStarted>(driverStartHandlers);
+            _driverStoppedDispatcher = new DispatchEventHandler<IDriverStopped>(driverStopHandlers);
+            _allocatedEvaluatorDispatcher = new DispatchEventHandler<IAllocatedEvaluator>(allocatedEvaluatorHandlers);
+            _failedEvaluatorDispatcher = new DispatchEventHandler<IFailedEvaluator>(failedEvaluatorHandlers);
+            _completedEvaluatorDispatcher = new DispatchEventHandler<ICompletedEvaluator>(completedEvaluatorHandlers);
+            _activeContextDispatcher = new DispatchEventHandler<IActiveContext>(activeContextHandlers);
+            _closedContextDispatcher = new DispatchEventHandler<IClosedContext>(closedContextHandlers);
+            _failedContextDispatcher = new DispatchEventHandler<IFailedContext>(failedContextHandlers);
+            _contextMessageDispatcher = new DispatchEventHandler<IContextMessage>(contextMessageHandlers);
+            _taskMessageDispatcher = new DispatchEventHandler<ITaskMessage>(taskMessageHandlers);
+            _failedTaskDispatcher = new DispatchEventHandler<IFailedTask>(failedTaskHandlers);
+            _runningTaskDispatcher = new DispatchEventHandler<IRunningTask>(runningTaskHandlers);
+            _completedTaskDispatcher = new DispatchEventHandler<ICompletedTask>(completedTaskHandlers);
+            _suspendedTaskDispatcher = new DispatchEventHandler<ISuspendedTask>(suspendedTaskHandlers);
+            _driverRestartedDispatcher = new DispatchEventHandler<IDriverRestarted>(driverRestartedHandlers);
+            _driverRestartActiveContextDispatcher = new DispatchEventHandler<IActiveContext>(driverRestartActiveContextHandlers);
+            _driverRestartRunningTaskDispatcher = new DispatchEventHandler<IRunningTask>(driverRestartRunningTaskHandlers);
+            _driverRestartCompletedDispatcher = new DispatchEventHandler<IDriverRestartCompleted>(driverRestartCompletedHandlers);
+            _driverRestartFailedEvaluatorDispatcher = new DispatchEventHandler<IFailedEvaluator>(driverRestartFailedEvaluatorHandlers);
+            _clientCloseDispatcher = new DispatchEventHandler<byte[]>(clientCloseHandlers);
+            _clientCloseWithMessageDispatcher = new DispatchEventHandler<byte[]>(clientCloseWithMessageHandlers);
+            _clientMessageDispatcher = new DispatchEventHandler<byte[]>(clientMessageHandlers);
+
+            foreach (var listener in traceListeners)
+            {
+                Logger.AddTraceListener(listener);
+            }
+            Log.Log(Level.Info, "Constructing DriverBridge");
+
+            if (Enum.TryParse(traceLevel.ToString(CultureInfo.InvariantCulture), out Level level))
+            {
+                Logger.SetCustomLevel(level);
+            }
+            else
+            {
+                Log.Log(Level.Warning, "Invalid trace level {0} provided, will by default use verbose level", traceLevel);
+            }
+            s_activeDispatchCounter = 0;
+        }
+
+        public async Task DispatchDriverRestartFailedEvaluatorEvent(IFailedEvaluator failedEvaluatorEvent)
+        {
+            await DispatchAsync(_driverRestartFailedEvaluatorDispatcher, failedEvaluatorEvent);
+        }
+
+        public async Task DispatchDriverRestartCompletedEvent(IDriverRestartCompleted driverRestartCompletedEvent)
+        {
+            await DispatchAsync(_driverRestartCompletedDispatcher, driverRestartCompletedEvent);
+        }
+
+        public async Task DispatchDriverRestartRunningTaskEvent(IRunningTask runningTaskEvent)
+        {
+            await DispatchAsync(_driverRestartRunningTaskDispatcher, runningTaskEvent);
+        }
+
+        public async Task DispatchDriverRestartActiveContextEvent(IActiveContext activeContextEvent)
+        {
+            await DispatchAsync(_driverRestartActiveContextDispatcher, activeContextEvent);
+        }
+
+        public async Task DispatchDriverRestartedEvent(IDriverRestarted driverRestartedEvent)
+        {
+            await DispatchAsync(_driverRestartedDispatcher, driverRestartedEvent);
+        }
+
+        public async Task DispatchCompletedTaskEvent(ICompletedTask completedTaskEvent)
+        {
+            await DispatchAsync(_completedTaskDispatcher, completedTaskEvent);
+        }
+
+        public async Task DispatchRunningTaskEvent(IRunningTask runningTaskEvent)
+        {
+            await DispatchAsync(_runningTaskDispatcher, runningTaskEvent);
+        }
+
+        public async Task DispatchFailedTaskEvent(IFailedTask failedTaskEvent)
+        {
+            await DispatchAsync(_failedTaskDispatcher, failedTaskEvent);
+        }
+
+        public async Task DispatchTaskMessageEvent(ITaskMessage taskMessageEvent)
+        {
+            await DispatchAsync(_taskMessageDispatcher, taskMessageEvent);
+        }
+
+        public async Task DispatchSuspendedTaskEvent(ISuspendedTask suspendedTask)
+        {
+            await DispatchAsync(_suspendedTaskDispatcher, suspendedTask);
+        }
+
+        public async Task DispatchContextMessageEvent(IContextMessage contextMessageEvent)
+        {
+            await DispatchAsync(_contextMessageDispatcher, contextMessageEvent);
+        }
+
+        public async Task DispatchFailedContextEvent(IFailedContext failedContextEvent)
+        {
+            await DispatchAsync(_failedContextDispatcher, failedContextEvent);
+        }
+
+        public async Task DispatchClosedContextEvent(IClosedContext closedContextEvent)
+        {
+            await DispatchAsync(_closedContextDispatcher, closedContextEvent);
+        }
+
+        public async Task DispatchActiveContextEvent(IActiveContext activeContextEvent)
+        {
+            await DispatchAsync(_activeContextDispatcher, activeContextEvent);
+        }
+
+        public async Task DispatchCompletedEvaluatorEvent(ICompletedEvaluator completedEvaluatorEvent)
+        {
+            await DispatchAsync(_completedEvaluatorDispatcher, completedEvaluatorEvent);
+        }
+
+        public async Task DispatchFailedEvaluatorEvent(IFailedEvaluator failedEvaluatorEvent)
+        {
+            await DispatchAsync(_failedEvaluatorDispatcher, failedEvaluatorEvent);
+        }
+
+        public async Task DispatchAllocatedEvaluatorEventAsync(IAllocatedEvaluator allocatedEvaluatorEvent)
+        {
+            await DispatchAsync(_allocatedEvaluatorDispatcher, allocatedEvaluatorEvent);
+        }
+
+        public async Task DispatchStartEventAsync(IDriverStarted startEvent)
+        {
+            await DispatchAsync(_driverStartedDispatcher, startEvent);
+        }
+
+        public async Task DispatchStopEvent(IDriverStopped stopEvent)
+        {
+            await DispatchAsync(_driverStoppedDispatcher, stopEvent);
+        }
+
+        public async Task DispatchClientCloseEvent()
+        {
+            await DispatchAsync(_clientCloseDispatcher, null);
+        }
+
+        public async Task DispatchClientCloseWithMessageEvent(byte[] message)
+        {
+            await DispatchAsync(_clientCloseWithMessageDispatcher, message);
+        }
+
+        public async Task DispatchClientMessageEvent(byte[] message)
+        {
+            await DispatchAsync(_clientMessageDispatcher, message);
+        }
+
+        private static async Task DispatchAsync<T>(DispatchEventHandler<T> handler, T message)
+        {
+            using (var operation = new DisposableOperation(() => handler.OnNext(message)))
+            {
+                await operation.Run();
+            }
+        }
+
+        private sealed class DisposableOperation : IDisposable
+        {
+            private readonly Action _operation;
+
+            public DisposableOperation(Action operation)
+            {
+                _operation = operation;
+            }
+
+            public async Task Run()
+            {
+                try
+                {
+                    Interlocked.Increment(ref s_activeDispatchCounter);
+                    await Task.Run(_operation);
+                }
+                catch (Exception ex)
+                {
+                    Log.Log(Level.Error, "Operation error", ex);
+                    throw;
+                }
+                finally
+                {
+                    Interlocked.Decrement(ref s_activeDispatchCounter);
+                }
+            }
+
+            public void Dispose()
+            {
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridgeConfiguration.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridgeConfiguration.cs
new file mode 100644
index 0000000..340d1f1
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridgeConfiguration.cs
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Util;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    internal sealed class DriverBridgeConfiguration : ConfigurationModuleBuilder
+    {
+        public static readonly RequiredImpl<IDriverClientService> DriverClientService = new RequiredImpl<IDriverClientService>();
+
+        public static readonly RequiredImpl<IDriverServiceClient> DriverServiceClient = new RequiredImpl<IDriverServiceClient>();
+
+        public static ConfigurationModule ConfigurationModule => new DriverBridgeConfiguration()
+            .BindImplementation(GenericType<IDriverClientService>.Class, DriverClientService)
+            .BindImplementation(GenericType<IDriverServiceClient>.Class, DriverServiceClient)
+            .Build();
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridgeEvaluatorRequestor.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridgeEvaluatorRequestor.cs
new file mode 100644
index 0000000..66a75a8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/DriverBridgeEvaluatorRequestor.cs
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Catalog;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    internal sealed class DriverBridgeEvaluatorRequestor : IEvaluatorRequestor
+    {
+        private readonly IDriverServiceClient _driverServiceClient;
+
+        [Inject]
+        private DriverBridgeEvaluatorRequestor(IDriverServiceClient driverServiceClient)
+        {
+            _driverServiceClient = driverServiceClient;
+        }
+
+        public IResourceCatalog ResourceCatalog { get; }
+
+        public void Submit(IEvaluatorRequest request)
+        {
+            _driverServiceClient.OnEvaluatorRequest(request);
+        }
+
+        public EvaluatorRequestBuilder NewBuilder()
+        {
+            return new EvaluatorRequestBuilder();
+        }
+
+        public EvaluatorRequestBuilder NewBuilder(IEvaluatorRequest request)
+        {
+            return new EvaluatorRequestBuilder(request);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeActiveContext.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeActiveContext.cs
new file mode 100644
index 0000000..0bfc210
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeActiveContext.cs
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeActiveContext : IActiveContext
+    {
+        private readonly IDriverServiceClient _driverServiceClient;
+
+        public string Id { get; }
+        public string EvaluatorId { get; }
+        public Optional<string> ParentId { get; }
+        public IEvaluatorDescriptor EvaluatorDescriptor { get; }
+
+        public BridgeActiveContext(
+            IDriverServiceClient driverServiceClient,
+            string id,
+            string evaluatorId,
+            Optional<string> parentId,
+            IEvaluatorDescriptor evaluatorDescriptor)
+        {
+            _driverServiceClient = driverServiceClient;
+            Id = id;
+            EvaluatorId = evaluatorId;
+            ParentId = parentId;
+            EvaluatorDescriptor = evaluatorDescriptor;
+        }
+
+        public void Dispose()
+        {
+            _driverServiceClient.OnContextClose(Id);
+        }
+
+        public void SubmitTask(IConfiguration taskConf)
+        {
+            _driverServiceClient.OnContextSubmitTask(Id, taskConf);
+        }
+
+        public void SubmitContext(IConfiguration contextConfiguration)
+        {
+            _driverServiceClient.OnContextSubmitContext(Id, contextConfiguration);
+        }
+
+        public void SubmitContextAndService(IConfiguration contextConfiguration, IConfiguration serviceConfiguration)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void SendMessage(byte[] message)
+        {
+            _driverServiceClient.OnContextMessage(Id, message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeAllocatedEvaluator.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeAllocatedEvaluator.cs
new file mode 100644
index 0000000..9dcc918
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeAllocatedEvaluator.cs
@@ -0,0 +1,163 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Common.Evaluator;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeAllocatedEvaluator : IAllocatedEvaluator
+    {
+        private readonly IDriverServiceClient _driverServiceClient;
+
+        private readonly IEvaluatorDescriptor _evaluatorDescriptor;
+
+        private readonly List<FileInfo> _addFiles = new List<FileInfo>();
+
+        private readonly List<FileInfo> _addLibraries = new List<FileInfo>();
+
+        public string Id { get; }
+
+        public EvaluatorType Type
+        {
+            get { return EvaluatorType.CLR; }
+            set
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public string NameServerInfo
+        {
+            get
+            {
+                throw new NotImplementedException();
+            }
+            set
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public string EvaluatorBatchId
+        {
+            get
+            {
+                throw new NotImplementedException();
+            }
+            set
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public BridgeAllocatedEvaluator(
+            string id,
+            IDriverServiceClient driverServiceClient,
+            IEvaluatorDescriptor evaluatorDescriptor)
+        {
+            Id = id;
+            _driverServiceClient = driverServiceClient;
+            _evaluatorDescriptor = evaluatorDescriptor;
+        }
+
+        public void Dispose()
+        {
+            _driverServiceClient.OnEvaluatorClose(Id);
+        }
+
+        public void SubmitContext(IConfiguration contextConfiguration)
+        {
+            _driverServiceClient.OnEvaluatorSubmit(
+                Id,
+                contextConfiguration,
+                Optional<IConfiguration>.Empty(),
+                Optional<IConfiguration>.Empty(),
+                _addFiles, _addLibraries);
+        }
+
+        public void SubmitContextAndService(IConfiguration contextConfiguration, IConfiguration serviceConfiguration)
+        {
+            _driverServiceClient.OnEvaluatorSubmit(
+                Id,
+                contextConfiguration,
+                Optional<IConfiguration>.Of(serviceConfiguration),
+                Optional<IConfiguration>.Empty(),
+                _addFiles, _addLibraries);
+        }
+
+        public void SubmitContextAndTask(IConfiguration contextConfiguration, IConfiguration taskConfiguration)
+        {
+            _driverServiceClient.OnEvaluatorSubmit(
+                Id,
+                contextConfiguration,
+                Optional<IConfiguration>.Empty(),
+                Optional<IConfiguration>.Of(taskConfiguration),
+                _addFiles, _addLibraries);
+        }
+
+        public void SubmitContextAndServiceAndTask(IConfiguration contextConfiguration, IConfiguration serviceConfiguration,
+            IConfiguration taskConfiguration)
+        {
+            _driverServiceClient.OnEvaluatorSubmit(
+                Id,
+                contextConfiguration,
+                Optional<IConfiguration>.Of(serviceConfiguration),
+                Optional<IConfiguration>.Of(taskConfiguration),
+                _addFiles, _addLibraries);
+        }
+
+        public void SubmitTask(IConfiguration taskConf)
+        {
+            var contextConfiguration =
+                ContextConfiguration.ConfigurationModule.Set(
+                    ContextConfiguration.Identifier, "RootContext_" + Id).Build();
+            _driverServiceClient.OnEvaluatorSubmit(
+                Id,
+                contextConfiguration,
+                Optional<IConfiguration>.Empty(),
+                Optional<IConfiguration>.Of(taskConf),
+                _addFiles, _addLibraries);
+        }
+
+        public IEvaluatorDescriptor GetEvaluatorDescriptor()
+        {
+            return _evaluatorDescriptor;
+        }
+
+        public void AddFile(string file)
+        {
+            _addFiles.Add(new FileInfo(file));
+        }
+
+        public void AddLibrary(string lib)
+        {
+            _addLibraries.Add(new FileInfo(lib));
+        }
+
+        public void AddFileResource(string file)
+        {
+            _addFiles.Add(new FileInfo(file));
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeClosedContext.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeClosedContext.cs
new file mode 100644
index 0000000..75c46c1
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeClosedContext.cs
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeClosedContext : IClosedContext
+    {
+        public string Id { get; }
+        public string EvaluatorId { get; }
+        public Optional<string> ParentId { get; }
+        public IEvaluatorDescriptor EvaluatorDescriptor { get; }
+        public IActiveContext ParentContext { get; }
+
+        public BridgeClosedContext(
+            string id,
+            string evaluatorId,
+            Optional<string> parentId,
+            IEvaluatorDescriptor evaluatorDescriptor,
+            IActiveContext parentContext)
+        {
+            Id = id;
+            EvaluatorId = evaluatorId;
+            ParentId = parentId;
+            EvaluatorDescriptor = evaluatorDescriptor;
+            ParentContext = parentContext;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeCompletedEvaluator.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeCompletedEvaluator.cs
new file mode 100644
index 0000000..99d94fa
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeCompletedEvaluator.cs
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Evaluator;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeCompletedEvaluator : ICompletedEvaluator
+    {
+        public string Id { get; }
+
+        public BridgeCompletedEvaluator(string id)
+        {
+            Id = id;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeCompletedTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeCompletedTask.cs
new file mode 100644
index 0000000..087fafd
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeCompletedTask.cs
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Task;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeCompletedTask : ICompletedTask
+    {
+        public byte[] Message { get; }
+        public string Id { get; }
+        public IActiveContext ActiveContext { get; }
+
+        public BridgeCompletedTask(byte[] message, string id, IActiveContext activeContext)
+        {
+            Message = message;
+            Id = id;
+            ActiveContext = activeContext;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeContextMessage.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeContextMessage.cs
new file mode 100644
index 0000000..4e394af
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeContextMessage.cs
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Context;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeContextMessage : IContextMessage
+    {
+        public byte[] Message { get; }
+        public string Id { get; }
+        public string MessageSourceId { get; }
+
+        public BridgeContextMessage(string id, string messageSourceId, byte[] message)
+        {
+            Message = message;
+            Id = id;
+            MessageSourceId = messageSourceId;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverRestartCompleted.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverRestartCompleted.cs
new file mode 100644
index 0000000..01db9e9
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverRestartCompleted.cs
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeDriverRestartCompleted : IDriverRestartCompleted
+    {
+        public DateTime CompletedTime { get; }
+        public bool IsTimedOut { get; }
+
+        public BridgeDriverRestartCompleted(DateTime completedTime, bool isTimedOut)
+        {
+            CompletedTime = completedTime;
+            IsTimedOut = isTimedOut;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverRestarted.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverRestarted.cs
new file mode 100644
index 0000000..ee73c65
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverRestarted.cs
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver;
+using System;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeDriverRestarted : IDriverRestarted
+    {
+        public DateTime StartTime { get; }
+        public ISet<string> ExpectedEvaluatorIds { get; }
+        public int ResubmissionAttempts { get; }
+
+        public BridgeDriverRestarted(DateTime startTime, ISet<string> expectedEvaluatorIds, int resubmissionAttempts)
+        {
+            StartTime = startTime;
+            ExpectedEvaluatorIds = expectedEvaluatorIds;
+            ResubmissionAttempts = resubmissionAttempts;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverStarted.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverStarted.cs
new file mode 100644
index 0000000..4ac7f4e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverStarted.cs
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal class BridgeDriverStarted : IDriverStarted
+    {
+        public DateTime StartTime { get; }
+
+        public BridgeDriverStarted(DateTime startTime)
+        {
+            StartTime = startTime;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverStopped.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverStopped.cs
new file mode 100644
index 0000000..aa5eab7
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeDriverStopped.cs
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal class BridgeDriverStopped : IDriverStopped
+    {
+        public DateTime StopTime { get; }
+
+        public BridgeDriverStopped(DateTime stopTime)
+        {
+            StopTime = stopTime;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedContext.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedContext.cs
new file mode 100644
index 0000000..1d190f2
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedContext.cs
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeFailedContext : IFailedContext
+    {
+        public string Id { get; }
+        public string EvaluatorId { get; }
+        public Optional<string> ParentId { get; }
+        public IEvaluatorDescriptor EvaluatorDescriptor { get; }
+        public Optional<IActiveContext> ParentContext { get; }
+
+        public BridgeFailedContext(
+            string id,
+            string evaluatorId,
+            IEvaluatorDescriptor evaluatorDescriptor,
+            Optional<IActiveContext> parentContext)
+        {
+            Id = id;
+            EvaluatorId = evaluatorId;
+            ParentId = Optional<string>.OfNullable(parentContext.OrElse(null)?.Id);
+            EvaluatorDescriptor = evaluatorDescriptor;
+            ParentContext = parentContext;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedEvaluator.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedEvaluator.cs
new file mode 100644
index 0000000..9bb24a4
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedEvaluator.cs
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Utilities;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeFailedEvaluator : IFailedEvaluator
+    {
+        public BridgeFailedEvaluator(
+            string id,
+            EvaluatorException evaluatorException,
+            IList<IFailedContext> failedContexts,
+            Optional<IFailedTask> failedTask)
+        {
+            Id = id;
+            EvaluatorException = evaluatorException;
+            FailedContexts = failedContexts;
+            FailedTask = failedTask;
+        }
+
+        public string Id { get; }
+        public EvaluatorException EvaluatorException { get; }
+        public IList<IFailedContext> FailedContexts { get; }
+        public Optional<IFailedTask> FailedTask { get; }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedTask.cs
new file mode 100644
index 0000000..23b1c53f
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeFailedTask.cs
@@ -0,0 +1,130 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Avro;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeFailedTask : IFailedTask
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(BridgeFailedTask));
+
+        private readonly Optional<IActiveContext> _activeContext;
+
+        private Exception _cause = null;
+
+        public BridgeFailedTask(Optional<IActiveContext> activeContext, string id, string message, byte[] data) :
+            this(activeContext, id, message, null, null, data)
+        {
+        }
+
+        public BridgeFailedTask(
+            Optional<IActiveContext> activeContext,
+            string id,
+            string message,
+            string description,
+            string reason,
+            byte[] data)
+        {
+            _activeContext = activeContext;
+            Id = id;
+            Message = message;
+            Description = Optional<string>.OfNullable(description);
+            Reason = Optional<string>.OfNullable(reason);
+            if (data != null)
+            {
+                var avroFailedTask = AvroJsonSerializer<AvroFailedTask>.FromBytes(data);
+
+                if (!id.Equals(avroFailedTask.identifier))
+                {
+                    Log.Log(Level.Error, "Task error id {0} does not match task id {1}", avroFailedTask.identifier, id);
+                }
+
+                // Data is simply the serialized Exception.ToString.
+                Data = Optional<byte[]>.OfNullable(avroFailedTask.data);
+
+                // Message can be overwritten in Java, if the C# Message is null and the Task failure is caused by an Evaluator failure.
+                Message = string.IsNullOrWhiteSpace(avroFailedTask.message)
+                    ? "No message in Failed Task."
+                    : avroFailedTask.message;
+
+                // Gets the Exception.
+                _cause = GetCause(avroFailedTask.cause, ByteUtilities.ByteArraysToString(avroFailedTask.data));
+
+                // This is always empty, even in Java.
+                Description = Optional<string>.Empty();
+            }
+            else
+            {
+                Log.Log(Level.Warning, "no exception data");
+                Data = Optional<byte[]>.Empty();
+            }
+        }
+
+        public string Id { get; }
+        public string Message { get; set; }
+        public Optional<string> Description { get; set; }
+        public Optional<string> Reason { get; set; }
+        public Optional<byte[]> Data { get; set; }
+
+        public Optional<IActiveContext> GetActiveContext()
+        {
+            return _activeContext;
+        }
+
+        /// <summary>
+        /// Returns the Exception causing the Failed Task.
+        /// </summary>
+        /// <returns>the Exception causing the Failed Task.</returns>
+        /// <remarks>
+        /// If the Exception was caused by a control flow error (start, stop, suspend),
+        /// a <see cref="TaskClientCodeException"/> is expected.
+        /// If the original Exception was not serializable, a <see cref="NonSerializableTaskException"/> is expected.
+        /// If the Exception was missing, presumably caused by a failed Evaluator, a
+        /// <see cref="TaskExceptionMissingException"/> is expected.
+        /// </remarks>
+        public Exception AsError()
+        {
+            return _cause;
+        }
+
+        private static Exception GetCause(byte[] serializedCause, string originalTaskExceptionToString)
+        {
+            // TODO[JIRA REEF-1422]: Distinguish between Java Task Exception and missing Exception.
+            if (ByteUtilities.IsNullOrEmpty(serializedCause))
+            {
+                return new TaskExceptionMissingException(
+                    "Task failed without an Exception, presumably caused by an Exception failure. Please inspect the FailedTask message.");
+            }
+            try
+            {
+                return (Exception)ByteUtilities.DeserializeFromBinaryFormat(serializedCause);
+            }
+            catch (SerializationException se)
+            {
+                return NonSerializableTaskException.UnableToDeserialize(originalTaskExceptionToString, se);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeRunningTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeRunningTask.cs
new file mode 100644
index 0000000..e469202
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeRunningTask.cs
@@ -0,0 +1,64 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeRunningTask : IRunningTask
+    {
+        private readonly IDriverServiceClient _driverServiceClient;
+
+        public string Id { get; }
+
+        public IActiveContext ActiveContext { get; }
+
+        public BridgeRunningTask(IDriverServiceClient driverServiceClient, string id, IActiveContext context)
+        {
+            _driverServiceClient = driverServiceClient;
+            Id = id;
+            ActiveContext = context;
+        }
+
+        public void Send(byte[] message)
+        {
+            _driverServiceClient.OnTaskMessage(Id, message);
+        }
+
+        public void Suspend(byte[] message)
+        {
+            _driverServiceClient.OnTaskSuspend(Id, Optional<byte[]>.Of(message));
+        }
+
+        public void Suspend()
+        {
+            _driverServiceClient.OnTaskSuspend(Id, Optional<byte[]>.Empty());
+        }
+
+        public void Dispose()
+        {
+            _driverServiceClient.OnTaskClose(Id, Optional<byte[]>.Empty());
+        }
+
+        public void Dispose(byte[] message)
+        {
+            _driverServiceClient.OnTaskClose(Id, Optional<byte[]>.Of(message));
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeSuspendedTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeSuspendedTask.cs
new file mode 100644
index 0000000..256a799
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeSuspendedTask.cs
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Task;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeSuspendedTask : ISuspendedTask
+    {
+        public byte[] Message { get; }
+        public string Id { get; }
+        public IActiveContext ActiveContext { get; }
+
+        public BridgeSuspendedTask(byte[] message, string id, IActiveContext activeContext)
+        {
+            Message = message;
+            Id = id;
+            ActiveContext = activeContext;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeTaskMessage.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeTaskMessage.cs
new file mode 100644
index 0000000..ed5d67e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/BridgeTaskMessage.cs
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Task;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class BridgeTaskMessage : ITaskMessage
+    {
+        public byte[] Message { get; }
+        public string TaskId { get; }
+        public string MessageSourceId { get; }
+
+        public BridgeTaskMessage(byte[] message, string taskId, string messageSourceId)
+        {
+            Message = message;
+            TaskId = taskId;
+            MessageSourceId = messageSourceId;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/EvaluatorDescriptor.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/EvaluatorDescriptor.cs
new file mode 100644
index 0000000..f28dd89
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/EvaluatorDescriptor.cs
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Catalog;
+using Org.Apache.REEF.Common.Evaluator;
+using Org.Apache.REEF.Common.Runtime;
+using Org.Apache.REEF.Driver.Evaluator;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class EvaluatorDescriptor : IEvaluatorDescriptor
+    {
+        public INodeDescriptor NodeDescriptor { get; }
+
+        public EvaluatorType EvaluatorType => EvaluatorType.CLR;
+
+        public int Memory { get; }
+        public int VirtualCore { get; }
+
+        public string Rack
+        {
+            get
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        public RuntimeName RuntimeName { get; }
+
+        public EvaluatorDescriptor(
+            INodeDescriptor nodeDescriptor,
+            int memory,
+            int virtualCore,
+            RuntimeName runtimeName = RuntimeName.Local)
+        {
+            NodeDescriptor = nodeDescriptor;
+            Memory = memory;
+            VirtualCore = virtualCore;
+            RuntimeName = runtimeName;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/NodeDescriptor.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/NodeDescriptor.cs
new file mode 100644
index 0000000..101f924
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/Events/NodeDescriptor.cs
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Catalog;
+using Org.Apache.REEF.Common.Catalog.Capabilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System.Net;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver.Events
+{
+    internal sealed class NodeDescriptor : INodeDescriptor
+    {
+        private static readonly Logger _log = Logger.GetLogger(typeof(NodeDescriptor));
+
+        public IPEndPoint InetSocketAddress { get; set; }
+        public string HostName { get; set; }
+        public CPU Cpu { get; set; }
+        public RAM Ram { get; set; }
+
+        public NodeDescriptor(IPEndPoint inetSocketAddress, string hostName, CPU cpu, RAM ram)
+        {
+            InetSocketAddress = inetSocketAddress;
+            HostName = hostName;
+            Cpu = cpu;
+            Ram = ram;
+        }
+
+        public NodeDescriptor(string ip, int port, string hostName, CPU cpu, RAM ram)
+        {
+            IPAddress address;
+            if (IPAddress.TryParse(ip, out address))
+            {
+                InetSocketAddress = new IPEndPoint(address, port);
+            }
+            else
+            {
+                _log.Log(Level.Error, "Could not parse ip address {0}", ip);
+            }
+            HostName = hostName;
+            Cpu = cpu;
+            Ram = ram;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/IDriverClientService.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/IDriverClientService.cs
new file mode 100644
index 0000000..6f30e4e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/IDriverClientService.cs
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    /// <summary>
+    /// The interface that initializes the driver client.
+    /// </summary>
+    internal interface IDriverClientService
+    {
+        /// <summary>
+        /// Start the driver client service.
+        /// </summary>
+        void Start();
+
+        /// <summary>
+        /// Await for termination.
+        /// </summary>
+        void AwaitTermination();
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/IDriverServiceClient.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/IDriverServiceClient.cs
new file mode 100644
index 0000000..1444a60
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Driver/IDriverServiceClient.cs
@@ -0,0 +1,128 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Org.Apache.REEF.Bridge.Core.Common.Driver
+{
+    /// <summary>
+    /// The interface for talking to the Java driver.
+    /// </summary>
+    internal interface IDriverServiceClient
+    {
+        /// <summary>
+        /// Initiate shutdown.
+        /// </summary>
+        void OnShutdown();
+
+        /// <summary>
+        /// Initiate shutdown with exception.
+        /// </summary>
+        /// <param name="ex">exception</param>
+        void OnShutdown(Exception ex);
+
+        /// <summary>
+        /// Set an alarm that will timeout it the given
+        /// amount of milliseconds.
+        /// </summary>
+        /// <param name="alarmId">Identifies the alarm</param>
+        /// <param name="timeoutMs">When to tigger the alarm in the future</param>
+        void OnSetAlarm(string alarmId, long timeoutMs);
+
+        /// <summary>
+        /// Request evalautor resources.
+        /// </summary>
+        /// <param name="evaluatorRequest">Request details</param>
+        void OnEvaluatorRequest(IEvaluatorRequest evaluatorRequest);
+
+        /// <summary>
+        /// Close the evaluator with the given identifier.
+        /// </summary>
+        /// <param name="evalautorId">Evaluator identifier</param>
+        void OnEvaluatorClose(string evalautorId);
+
+        /// <summary>
+        /// Submit the evalautor with the given configuration.
+        /// </summary>
+        /// <param name="evaluatorId">Evaluator identifier</param>
+        /// <param name="contextConfiguration">Context configuration</param>
+        /// <param name="serviceConfiguration">Service configuration</param>
+        /// <param name="taskConfiguration">Task configuration</param>
+        /// <param name="addFileList">Files that should be included</param>
+        /// <param name="addLibraryList">Libraries that should be included</param>
+        void OnEvaluatorSubmit(
+            string evaluatorId,
+            IConfiguration contextConfiguration,
+            Optional<IConfiguration> serviceConfiguration,
+            Optional<IConfiguration> taskConfiguration,
+            List<FileInfo> addFileList,
+            List<FileInfo> addLibraryList);
+
+        /// <summary>
+        /// Close the context with the given identifier.
+        /// </summary>
+        /// <param name="contextId">Context identifier</param>
+        void OnContextClose(string contextId);
+
+        /// <summary>
+        /// Submit a new context with the given configuration.
+        /// </summary>
+        /// <param name="contextId">Context identifier through which a new context will be created</param>
+        /// <param name="contextConfiguration">Configuration of the new (child) context</param>
+        void OnContextSubmitContext(string contextId, IConfiguration contextConfiguration);
+
+        /// <summary>
+        /// Submit a task via the given context.
+        /// </summary>
+        /// <param name="contextId">Context identifier</param>
+        /// <param name="taskConfiguration">Task configuration</param>
+        void OnContextSubmitTask(string contextId, IConfiguration taskConfiguration);
+
+        /// <summary>
+        /// Send a message to the given context.
+        /// </summary>
+        /// <param name="contextId">Context identifier</param>
+        /// <param name="message">Message to send</param>
+        void OnContextMessage(string contextId, byte[] message);
+
+        /// <summary>
+        /// Close the task with an optional message.
+        /// </summary>
+        /// <param name="taskId">Task identifier</param>
+        /// <param name="message">Optional message</param>
+        void OnTaskClose(string taskId, Optional<byte[]> message);
+
+        /// <summary>
+        /// Suspend the task with an optional message.
+        /// </summary>
+        /// <param name="taskId">Task identifier to suspend</param>
+        /// <param name="message">Optional message</param>
+        void OnTaskSuspend(string taskId, Optional<byte[]> message);
+
+        /// <summary>
+        /// Send a message to the task.
+        /// </summary>
+        /// <param name="taskId">Task identifier</param>
+        /// <param name="message">Message to send</param>
+        void OnTaskMessage(string taskId, byte[] message);
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Org.Apache.REEF.Bridge.Core.Common.csproj b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Org.Apache.REEF.Bridge.Core.Common.csproj
new file mode 100644
index 0000000..403e46e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Org.Apache.REEF.Bridge.Core.Common.csproj
@@ -0,0 +1,36 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<Project>
+  <PropertyGroup>
+    <AssemblyName>Org.Apache.REEF.Bridge.Core.Common</AssemblyName>
+    <Description>REEF Bridge Core Common</Description>
+    <PackageTags>REEF Bridge Core Common</PackageTags>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+  <Import Project="..\build.props" />
+  <ItemGroup>
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Proto\Org.Apache.REEF.Bridge.Core.Proto.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Tang\Org.Apache.REEF.Tang.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Utilities\Org.Apache.REEF.Utilities.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Driver\Org.Apache.REEF.Driver.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Wake\Org.Apache.REEF.Wake.csproj" />
+  </ItemGroup>
+  <Import Project="..\build.targets" />
+</Project>
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Properties/AssemblyInfo.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6c75063
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Common/Properties/AssemblyInfo.cs
@@ -0,0 +1,21 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Grpc")]
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Driver")]
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Driver/DriverLauncher.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Driver/DriverLauncher.cs
new file mode 100644
index 0000000..8c45597
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Driver/DriverLauncher.cs
@@ -0,0 +1,90 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using System.IO;
+using Grpc.Core;
+using Grpc.Core.Logging;
+using Org.Apache.REEF.Bridge.Core.Grpc.Driver;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Implementations.Configuration;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using Org.Apache.REEF.Wake.Time;
+
+namespace Org.Apache.REEF.Bridge.Core.Driver
+{
+    /// <summary>
+    /// Used to launch the C# driver client.
+    /// </summary>
+    public sealed class DriverLauncher
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DriverLauncher));
+
+        private readonly IConfigurationSerializer _configurationSerializer;
+
+        [Inject]
+        private DriverLauncher(IConfigurationSerializer configurationSerializer)
+        {
+            _configurationSerializer = configurationSerializer;
+        }
+
+        private IConfiguration GetDriverClientConfiguration(string configFile, string driverServicePort)
+        {
+            if (!File.Exists(configFile))
+            {
+                // If we reached this, we weren't able to find the configuration file.
+                var message = $"Unable to find brigde configuration. Paths checked: [\'{configFile}\']";
+
+                Log.Log(Level.Error, message);
+                throw new FileNotFoundException(message);
+            }
+            else
+            {
+                return Configurations.Merge(_configurationSerializer.FromFile(configFile),
+                    TangFactory.GetTang().NewConfigurationBuilder()
+                        .BindNamedParameter(typeof(DriverServicePort), driverServicePort)
+                        .Build());
+
+            }
+        }
+
+        public static void Main(string[] args)
+        {
+            if (args.Length != 2)
+            {
+                var message = $"Driver client launcher takes a two arguments. Found {args}";
+                Log.Log(Level.Error, message);
+                throw new ArgumentException(message);
+            }
+            else
+            {
+                Log.Log(Level.Info, "Launching driver client with driver service port {0} config file {1}", args[0], args[1]);
+            }
+            GrpcEnvironment.SetLogger(new ConsoleLogger());
+            Log.Log(Level.Info, "Path of executing assembly{0}", ClientUtilities.GetPathToExecutingAssembly());
+            var launcher = TangFactory.GetTang().NewInjector().GetInstance<DriverLauncher>();
+            var driverClientConfig = launcher.GetDriverClientConfiguration(args[0], args[1]);
+            var clock = TangFactory.GetTang().NewInjector(driverClientConfig).GetInstance<IClock>();
+            clock.Run();
+
+            Log.Log(Level.Info, "Driver client clock exit.");
+        }
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Driver/Org.Apache.REEF.Bridge.Core.Driver.csproj b/lang/cs/Org.Apache.REEF.Bridge.Core.Driver/Org.Apache.REEF.Bridge.Core.Driver.csproj
new file mode 100644
index 0000000..107759a
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Driver/Org.Apache.REEF.Bridge.Core.Driver.csproj
@@ -0,0 +1,34 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<Project>
+  <PropertyGroup>
+    <AssemblyName>Org.Apache.REEF.Bridge.Core.Driver</AssemblyName>
+    <Description>REEF Bridge Core Driver</Description>
+    <PackageTags>REEF Bridge Core Driver</PackageTags>
+  </PropertyGroup>
+
+  <Import Project="..\build.App.props" />
+  <ItemGroup>
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Grpc\Org.Apache.REEF.Bridge.Core.Grpc.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Tang\Org.Apache.REEF.Tang.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Wake\Org.Apache.REEF.Wake.csproj" />
+  </ItemGroup>
+  <Import Project="..\build.targets" />
+</Project>
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientLauncher.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientLauncher.cs
new file mode 100644
index 0000000..13b1f9d
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientLauncher.cs
@@ -0,0 +1,235 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Google.Protobuf;
+using Grpc.Core;
+using Org.Apache.REEF.Bridge.Core.Common.Client;
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime.Proto;
+using Org.Apache.REEF.Bridge.Core.Common.Driver;
+using Org.Apache.REEF.Bridge.Core.Grpc.Driver;
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Common.Files;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Implementations.Configuration;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Client
+{
+    internal sealed class ClientLauncher : IClientLauncher
+    {
+        private const string SoFileNameExtension = ".so";
+        private const string DylibFileNameExtension = ".dylib";
+        private const string DllFileNameExtension = ".dll";
+        private const string ExeFileNameExtension = ".exe";
+        private const string JarFileNameExtension = ".jar";
+        private const string ConfigFileNameExtension = ".config";
+
+        private const string JavaClientLauncherClass = "org.apache.reef.bridge.client.grpc.ClientLauncher";
+
+        private const string DriverExe = "Org.Apache.REEF.Bridge.Core.Driver.exe";
+        private const string DriverDll = "Org.Apache.REEF.Bridge.Core.Driver.dll";
+
+        private static readonly string jsonSDK = @"
+{
+  ""runtimeOptions"": {
+        ""tfm"": ""netcoreapp2.0"",
+        ""framework"": {
+            ""name"": ""Microsoft.NETCore.App"",
+            ""version"": ""2.0.0""
+        }
+    }
+}
+";
+
+        private static readonly Logger Log = Logger.GetLogger(typeof(ClientLauncher));
+
+        private readonly ClientService _clientService;
+
+        private readonly DriverClientConfiguration _driverClientConfiguration;
+
+        private readonly REEFFileNames _reefFileNames;
+
+        private readonly IConfigurationSerializer _configurationSerializer;
+
+        private readonly JavaClientLauncher _javaClientLauncher;
+
+        private readonly Server _grpcServer;
+
+        private readonly int _grpcServerPort;
+
+        [Inject]
+        private ClientLauncher(
+            ClientService clientService,
+            JavaClientLauncher javaClientLauncher,
+            REEFFileNames reefFileNames,
+            IConfigurationSerializer configurationSerializer,
+            DriverClientParameters driverRuntimeProto,
+            IRuntimeProtoProvider runtimeProtoProvider)
+        {
+            _clientService = clientService;
+            _javaClientLauncher = javaClientLauncher;
+            _reefFileNames = reefFileNames;
+            _configurationSerializer = configurationSerializer;
+            _driverClientConfiguration = driverRuntimeProto.Proto;
+            runtimeProtoProvider.SetParameters(_driverClientConfiguration);
+            _grpcServer = new Server
+            {
+                Services = { BridgeClient.BindService(clientService) },
+                Ports = { new ServerPort("localhost", 0, ServerCredentials.Insecure) }
+            };
+            _grpcServer.Start();
+            Log.Log(Level.Info, "Server port any {0}", _grpcServer.Ports.Any());
+            foreach (var serverPort in _grpcServer.Ports)
+            {
+                Log.Log(Level.Info, "Server port {0}", serverPort.BoundPort);
+                _grpcServerPort = serverPort.BoundPort;
+            }
+        }
+
+        public void Dispose()
+        {
+            _grpcServer.ShutdownAsync();
+        }
+
+        public async Task<LauncherStatus> SubmitAsync(
+            IConfiguration driverAppConfiguration,
+            CancellationToken cancellationToken)
+        {
+            var driverClientConfiguration =
+                Configurations.Merge(driverAppConfiguration,
+                    DriverBridgeConfiguration.ConfigurationModule
+                        .Set(DriverBridgeConfiguration.DriverServiceClient, GenericType<DriverServiceClient>.Class)
+                        .Set(DriverBridgeConfiguration.DriverClientService, GenericType<DriverClientService>.Class)
+                        .Build());
+            var jobFolder = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
+            Log.Log(Level.Info, "Job folder {0}", jobFolder);
+            Directory.CreateDirectory(jobFolder.FullName);
+            AddDependencies(jobFolder, driverClientConfiguration);
+            // Launch command
+            if (File.Exists(DriverExe))
+            {
+                _driverClientConfiguration.DriverClientLaunchCommand = string.Format(
+                    @"cmd.exe /c {0} {1}",
+                    Path.Combine(_reefFileNames.GetGlobalFolderPath(), DriverExe),
+                    _reefFileNames.GetClrDriverConfigurationPath());
+            }
+            else
+            {
+                _driverClientConfiguration.DriverClientLaunchCommand = string.Format(
+                    @"dotnet {0} {1}",
+                    Path.Combine(_reefFileNames.GetGlobalFolderPath(), DriverDll),
+                    _reefFileNames.GetClrDriverConfigurationPath());
+            }
+
+            var driverClientConfigFile = Path.Combine(jobFolder.FullName, "driverclient.json");
+            using (var outputFile = new StreamWriter(driverClientConfigFile))
+            {
+                outputFile.Write(JsonFormatter.Default.Format(_driverClientConfiguration));
+            }
+            // Submit a new job
+            _clientService.Reset();
+            var task = _javaClientLauncher.LaunchAsync(JavaLoggingSetting.Info,
+                JavaClientLauncherClass,
+                new[] { driverClientConfigFile, _grpcServerPort.ToString() },
+                cancellationToken);
+            lock (_clientService)
+            {
+                while (!_clientService.IsDone && !cancellationToken.IsCancellationRequested)
+                {
+                    Monitor.Wait(_clientService, TimeSpan.FromMinutes(1));
+                }
+            }
+            await task;
+            return _clientService.LauncherStatus;
+        }
+
+        private void AddDependencies(FileSystemInfo jobFolder, IConfiguration driverClientConfiguration)
+        {
+            // driver client configuration
+            var driverClientConfigurationFile = Path.GetFullPath(Path.Combine(
+                jobFolder.FullName,
+                _reefFileNames.GetClrDriverConfigurationName()));
+            _configurationSerializer.ToFile(driverClientConfiguration, driverClientConfigurationFile);
+            _driverClientConfiguration.LocalFiles.Add(driverClientConfigurationFile);
+
+            /*
+            var jsonSDKFile = Path.Combine(jobFolder.FullName, "Org.Apache.REEF.Bridge.Core.Driver.runtimeconfig.json");
+            File.WriteAllText(jsonSDKFile, jsonSDK);
+            _driverClientConfiguration.GlobalFiles.Add(jsonSDKFile);
+            */
+
+            // resource files
+            var a = typeof(ClientLauncher).Assembly;
+            foreach (var name in a.GetManifestResourceNames())
+            {
+                Log.Log(Level.Info, "Extracting resource {0}", name);
+                var resource = a.GetManifestResourceStream(name);
+                using (var file = new FileStream(name, FileMode.Create, FileAccess.Write))
+                {
+                    resource.CopyTo(file);
+                }
+            }
+
+            var directory = ClientUtilities.GetPathToExecutingAssembly();
+            {
+                if (Directory.Exists(directory))
+                {
+                    // For input paths that are directories, extract only files of a predetermined type
+                    _driverClientConfiguration.GlobalFiles.Add(
+                        Directory.GetFiles(directory).Where(IsAssemblyToCopy));
+                }
+                else
+                {
+                    // Throw if a path input was not a file or a directory
+                    throw new FileNotFoundException($"Global Assembly Directory not Found: {directory}");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Returns true, if the given file path references a DLL or EXE or JAR.
+        /// </summary>
+        /// <param name="filePath"></param>
+        /// <returns></returns>
+        private static bool IsAssemblyToCopy(string filePath)
+        {
+            var fileName = Path.GetFileName(filePath);
+            if (string.IsNullOrWhiteSpace(fileName))
+            {
+                return false;
+            }
+
+            var lowerCasePath = fileName.ToLower();
+            return lowerCasePath.EndsWith(DllFileNameExtension) ||
+                   lowerCasePath.EndsWith(ExeFileNameExtension) ||
+                   lowerCasePath.EndsWith(DylibFileNameExtension) ||
+                   lowerCasePath.EndsWith(SoFileNameExtension) ||
+                   lowerCasePath.EndsWith(ConfigFileNameExtension) ||
+                   lowerCasePath.EndsWith(JarFileNameExtension);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientLauncherFactory.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientLauncherFactory.cs
new file mode 100644
index 0000000..42fcedb
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientLauncherFactory.cs
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client;
+using Org.Apache.REEF.Tang.Implementations.Configuration;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Client
+{
+    /// <summary>
+    /// Factory class for creating a ClientLauncher
+    /// </summary>
+    public static class ClientLauncherFactory
+    {
+        /// <summary>
+        /// Get a client launcher that does not include a client configuration, which
+        /// will default to all default client handlers e.g., <see cref="DefaultRunningJobHandler"/>
+        /// </summary>
+        /// <param name="runtimeConfiguration">One of YARN, Local, Azure Batch, etc. runtime configuration</param>
+        /// <param name="driverRuntimeConfiguration">The core driver runtime configuration <see cref="DriverRuntimeConfiguration"/></param>
+        /// <returns>ClientLauncher</returns>
+        public static IClientLauncher GetLauncher(
+            IConfiguration runtimeConfiguration,
+            IConfiguration driverRuntimeConfiguration)
+        {
+            return GetLauncher(runtimeConfiguration, driverRuntimeConfiguration, Optional<IConfiguration>.Empty());
+        }
+
+        /// <summary>
+        /// Get a client launcher that optionally includes a client configuration.
+        /// </summary>
+        /// <param name="runtimeConfiguration">One of YARN, Local, Azure Batch, etc. runtime configuration</param>
+        /// <param name="driverRuntimeConfiguration">The core driver runtime configuration <see cref="DriverRuntimeConfiguration"/></param>
+        /// <param name="clientConfiguration">Client configuration <see cref="ClientConfiguration"/></param>
+        /// <returns></returns>
+        public static IClientLauncher GetLauncher(
+            IConfiguration runtimeConfiguration,
+            IConfiguration driverRuntimeConfiguration,
+            Optional<IConfiguration> clientConfiguration)
+        {
+            return TangFactory.GetTang()
+                .NewInjector(Configurations.Merge(
+                    runtimeConfiguration,
+                    driverRuntimeConfiguration,
+                    clientConfiguration.OrElse(TangFactory.GetTang().NewConfigurationBuilder().Build())))
+                .GetInstance<ClientLauncher>();
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientService.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientService.cs
new file mode 100644
index 0000000..cc56c6e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/ClientService.cs
@@ -0,0 +1,216 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Google.Protobuf;
+using Grpc.Core;
+using Org.Apache.REEF.Bridge.Core.Common.Client;
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config;
+using Org.Apache.REEF.Bridge.Core.Common.Client.Events;
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Void = Org.Apache.REEF.Bridge.Core.Proto.Void;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Client
+{
+    /// <summary>
+    /// gRPC based client service.
+    /// </summary>
+    internal sealed class ClientService : BridgeClient.BridgeClientBase, IClientService
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(ClientService));
+
+        private static readonly Void Void = new Void();
+
+        private readonly IObserver<ISubmittedJob> _submittedJobHandler;
+
+        private readonly IObserver<IRunningJob> _runningJobHandler;
+
+        private readonly IObserver<ICompletedJob> _completedJobHandler;
+
+        private readonly IObserver<IFailedJob> _failedJobHandler;
+
+        private readonly IObserver<IJobMessage> _jobMessageHandler;
+
+        private readonly IObserver<IFailedRuntime> _failedRuntimeHandler;
+
+        private readonly IObserver<IWakeError> _wakeErrorHandler;
+
+        private REEFClient.REEFClientClient _clientStub = null;
+
+        private string _jobId = "unknown";
+
+        [Inject]
+        private ClientService(
+            [Parameter(Value = typeof(ClientParameters.SubmittedJobHandler))] IObserver<ISubmittedJob> submittedJobHandler,
+            [Parameter(Value = typeof(ClientParameters.RunningJobHandler))] IObserver<IRunningJob> runningJobHandler,
+            [Parameter(Value = typeof(ClientParameters.CompletedJobHandler))] IObserver<ICompletedJob> completedJobHandler,
+            [Parameter(Value = typeof(ClientParameters.FailedJobHandler))] IObserver<IFailedJob> failedJobHandler,
+            [Parameter(Value = typeof(ClientParameters.JobMessageHandler))] IObserver<IJobMessage> jobMessageHandler,
+            [Parameter(Value = typeof(ClientParameters.FailedRuntimeHandler))] IObserver<IFailedRuntime> failedRuntimeHandler,
+            [Parameter(Value = typeof(ClientParameters.WakeErrorHandler))] IObserver<IWakeError> wakeErrorHandler)
+        {
+            _submittedJobHandler = submittedJobHandler;
+            _runningJobHandler = runningJobHandler;
+            _completedJobHandler = completedJobHandler;
+            _failedJobHandler = failedJobHandler;
+            _jobMessageHandler = jobMessageHandler;
+            _failedRuntimeHandler = failedRuntimeHandler;
+            _wakeErrorHandler = wakeErrorHandler;
+            LauncherStatus = LauncherStatus.InitStatus;
+        }
+
+        public bool IsDone => LauncherStatus.IsDone;
+
+        public void Reset()
+        {
+            LauncherStatus = LauncherStatus.InitStatus;
+        }
+
+        public LauncherStatus LauncherStatus { get; private set; }
+
+        public void Close(byte[] message = null)
+        {
+            try
+            {
+                _clientStub?.DriverControlHandler(new DriverControlOp()
+                {
+                    JobId = _jobId,
+                    Message = message == null ? ByteString.Empty : ByteString.CopyFrom(message),
+                    Operation = DriverControlOp.Types.Operation.Close
+                });
+            }
+            catch (Exception e)
+            {
+                Log.Log(Level.Warning, "exception occurred when trying to close job", e);
+            }
+            LauncherStatus = LauncherStatus.ForceCloseStatus;
+            _clientStub = null;
+        }
+
+        public void Send(byte[] message)
+        {
+            if (_clientStub != null)
+            {
+                _clientStub.DriverControlHandler(new DriverControlOp()
+                {
+                    JobId = _jobId,
+                    Message = ByteString.CopyFrom(message),
+                    Operation = DriverControlOp.Types.Operation.Message
+                });
+            }
+            else
+            {
+                throw new IllegalStateException("Client service is closed");
+            }
+        }
+
+        public override Task<Void> RegisterREEFClient(REEFClientRegistration request, ServerCallContext context)
+        {
+            Log.Log(Level.Info, "REEF Client registered on port {0}", request.Port);
+            Channel driverServiceChannel = new Channel("127.0.0.1", (int)request.Port, ChannelCredentials.Insecure);
+            _clientStub = new REEFClient.REEFClientClient(driverServiceChannel);
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> JobMessageHandler(JobMessageEvent request, ServerCallContext context)
+        {
+            Log.Log(Level.Info, "Job message from job id {0}", request.JobId);
+            _jobMessageHandler.OnNext(new JobMessage(request.JobId, request.Message.ToByteArray()));
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> JobSumittedHandler(JobSubmittedEvent request, ServerCallContext context)
+        {
+            Log.Log(Level.Info, "Job id {0} submitted", request.JobId);
+            UpdateStatusAndNotify(LauncherStatus.SubmittedStatus);
+            _submittedJobHandler.OnNext(new SubmittedJob(request.JobId));
+            _jobId = request.JobId;
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> JobRunningHandler(JobRunningEvent request, ServerCallContext context)
+        {
+            Log.Log(Level.Info, "Job id {0} running", request.JobId);
+            UpdateStatusAndNotify(LauncherStatus.RunningStatus);
+            _runningJobHandler.OnNext(new RunningJob(this, request.JobId));
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> JobCompletedHandler(JobCompletedEvent request, ServerCallContext context)
+        {
+            if (IsDone) return Task.FromResult(Void);
+            Log.Log(Level.Info, "Job id {0} completed", request.JobId);
+            UpdateStatusAndNotify(LauncherStatus.CompletedStatus);
+            _completedJobHandler.OnNext(new CompletedJob(request.JobId));
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> JobFailedHandler(JobFailedEvent request, ServerCallContext context)
+        {
+            if (IsDone) return Task.FromResult(Void);
+            Log.Log(Level.Info, "Job id {0} failed on {1}", request.JobId, request.Exception.Name);
+            var jobFailedEvent = new FailedJob(request.JobId,
+                request.Exception.Message,
+                request.Exception.Data.ToByteArray());
+            UpdateStatusAndNotify(LauncherStatus.Failed(jobFailedEvent.AsError()));
+            _failedJobHandler.OnNext(jobFailedEvent);
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> RuntimeErrorHandler(ExceptionInfo request, ServerCallContext context)
+        {
+            if (!IsDone)
+            {
+                Log.Log(Level.Info, "Runtime error {0}", request.Message);
+                UpdateStatusAndNotify(LauncherStatus.FailedStatus);
+                _failedRuntimeHandler.OnNext(new FailedRuntime(_jobId, request.Message, request.Data.ToByteArray()));
+            }
+
+            return Task.FromResult(Void);
+        }
+
+        public override Task<Void> WakeErrorHandler(ExceptionInfo request, ServerCallContext context)
+        {
+            if (!IsDone)
+            {
+                Log.Log(Level.Info, "Wake error {0}", request.Message);
+                UpdateStatusAndNotify(LauncherStatus.FailedStatus);
+                _wakeErrorHandler.OnNext(new WakeError(_jobId,
+                    request.Message,
+                    Optional<byte[]>.Of(request.Data.ToByteArray())));
+            }
+
+            return Task.FromResult(Void);
+        }
+
+        private void UpdateStatusAndNotify(LauncherStatus status)
+        {
+            lock (this)
+            {
+                LauncherStatus = status;
+                Monitor.PulseAll(this);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/DriverClientParameters.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/DriverClientParameters.cs
new file mode 100644
index 0000000..7f435fb
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Client/DriverClientParameters.cs
@@ -0,0 +1,78 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config;
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using System.Collections.Generic;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Client
+{
+    internal sealed class DriverClientParameters
+    {
+        public DriverClientConfiguration Proto { get; }
+
+        [Inject]
+        private DriverClientParameters(
+            OsType osType,
+            [Parameter(Value = typeof(DriverRuntimeParameters.JobId))] string jobId,
+            [Parameter(Value = typeof(DriverRuntimeParameters.JobSubmissionDirectory))] string jobSubmissionDirectory,
+            [Parameter(Value = typeof(DriverRuntimeParameters.DriverCpuCores))] int driverCpuCores,
+            [Parameter(Value = typeof(DriverRuntimeParameters.DriverMemory))] int driverMemory,
+            [Parameter(Value = typeof(DriverRuntimeParameters.GlobalAssemblies))] ISet<string> globalAssemblies,
+            [Parameter(Value = typeof(DriverRuntimeParameters.LocalAssemblies))] ISet<string> localAssemblies,
+            [Parameter(Value = typeof(DriverRuntimeParameters.GlobalFiles))] ISet<string> globalFiles,
+            [Parameter(Value = typeof(DriverRuntimeParameters.LocalFiles))] ISet<string> localFiles,
+            [Parameter(Value = typeof(DriverRuntimeParameters.EnableDriverRestart))] bool enableDriverRestart,
+            [Parameter(Value = typeof(DriverRuntimeParameters.TcpPortRangeBegin))] int tcpPortRangeBegin,
+            [Parameter(Value = typeof(DriverRuntimeParameters.TcpPortRangeCount))] int tcpPortRangeCount,
+            [Parameter(Value = typeof(DriverRuntimeParameters.TcpPortRangeTryCount))] int tcpPortRangeTryCount,
+            [Parameter(Value = typeof(DriverRuntimeParameters.RestartEvaluatorRecoverySeconds))] int restartEvaluatorRecoverySeconds)
+        {
+            Proto = new DriverClientConfiguration()
+            {
+                Jobid = jobId,
+                DriverJobSubmissionDirectory = jobSubmissionDirectory,
+                CpuCores = (uint)driverCpuCores,
+                MemoryMb = (uint)driverMemory,
+                DriverRestartEnable = enableDriverRestart,
+                DriverRestartEvaluatorRecoverySeconds = (uint)restartEvaluatorRecoverySeconds,
+                TcpPortRangeBegin = (uint)tcpPortRangeBegin,
+                TcpPortRangeCount = (uint)tcpPortRangeCount,
+                TcpPortRangeTryCount = (uint)tcpPortRangeTryCount
+            };
+            Proto.GlobalLibraries.Add(globalAssemblies);
+            Proto.GlobalFiles.Add(globalFiles);
+            Proto.LocalLibraries.Add(localAssemblies);
+            Proto.LocalFiles.Add(localFiles);
+            switch (osType.Type)
+            {
+                case OsType.Os.Windows:
+                    Proto.OperatingSystem = DriverClientConfiguration.Types.OS.Windows;
+                    break;
+
+                case OsType.Os.Linux:
+                    Proto.OperatingSystem = DriverClientConfiguration.Types.OS.Linux;
+                    break;
+
+                default:
+                    throw new IllegalStateException("Unknown operating system type " + osType.Type);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverClientService.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverClientService.cs
new file mode 100644
index 0000000..79a6a75
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverClientService.cs
@@ -0,0 +1,738 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Grpc.Core;
+using Org.Apache.REEF.Bridge.Core.Common.Driver;
+using Org.Apache.REEF.Bridge.Core.Common.Driver.Events;
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Common.Catalog.Capabilities;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Common.Runtime;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Threading.Tasks;
+using Void = Org.Apache.REEF.Bridge.Core.Proto.Void;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Driver
+{
+    internal class DriverClientService : DriverClient.DriverClientBase, IDriverClientService
+    {
+        private static readonly Logger Logger = Logger.GetLogger(typeof(DriverClientService));
+
+        private static readonly Void Void = new Void();
+
+        private readonly object _lock = new object();
+
+        private readonly Server _server;
+
+        private readonly int _serverPort;
+
+        private readonly IInjector _injector;
+
+        private readonly BridgeClock _bridgeClock;
+
+        private readonly DriverServiceClient _driverServiceClient;
+
+        private readonly IDictionary<string, BridgeActiveContext> _activeContexts =
+            new Dictionary<string, BridgeActiveContext>();
+
+        private readonly IDictionary<string, BridgeRunningTask> _runningTasks =
+            new Dictionary<string, BridgeRunningTask>();
+
+        private DriverBridge _driverBridge;
+
+        private bool _receivedStartEvent;
+
+        private bool IsIdle
+        {
+            get
+            {
+                lock (_lock)
+                {
+                    return _receivedStartEvent && DriverBridge.IsIdle && _bridgeClock.IsIdle();
+                }
+            }
+        }
+
+        [Inject]
+        private DriverClientService(
+            IInjector injector,
+            BridgeClock bridgeClock,
+            DriverServiceClient driverServiceClient)
+        {
+            _receivedStartEvent = false;
+            _injector = injector;
+            _bridgeClock = bridgeClock;
+            _driverServiceClient = driverServiceClient;
+            _server = new Server
+            {
+                Services = { DriverClient.BindService(this) },
+                Ports = { new ServerPort("localhost", 0, ServerCredentials.Insecure) }
+            };
+            _server.Start();
+            foreach (var serverPort in _server.Ports)
+            {
+                Logger.Log(Level.Info, "Server port {0}", serverPort.BoundPort);
+                _serverPort = serverPort.BoundPort;
+            }
+
+            Logger.Log(Level.Info, "Client service started on port {0}", _serverPort);
+        }
+
+        #region Driver Client Service implementation
+
+        public void Start()
+        {
+            try
+            {
+                // could throw application level exception
+                _driverBridge = _injector.GetInstance<DriverBridge>();
+                _driverServiceClient.RegisterDriverClientService("localhost", _serverPort);
+            }
+            catch (Exception ex)
+            {
+                Logger.Log(Level.Error, "Driver application creation error", ex);
+                _driverServiceClient.RegisterDriverClientService(ex);
+                _server.ShutdownAsync();
+            }
+        }
+
+        public void AwaitTermination()
+        {
+            Logger.Log(Level.Info, "Awaiting client server termination");
+            _server.ShutdownTask.Wait();
+            Logger.Log(Level.Info, "Client server terminated");
+        }
+
+        #endregion Driver Client Service implementation
+
+        public override async Task<Void> AlarmTrigger(AlarmTriggerInfo request, ServerCallContext context)
+        {
+            await _bridgeClock.OnNextAsync(new BridgeClock.AlarmInfo
+            {
+                AlarmId = request.AlarmId,
+                Timestamp = request.Timestamp
+            });
+            return Void;
+        }
+
+        public override Task<IdleStatus> IdlenessCheckHandler(Void request, ServerCallContext context)
+        {
+            return Task.FromResult(new IdleStatus
+            {
+                IsIdle = IsIdle,
+                Reason = "Driver client"
+            });
+        }
+
+        public override async Task<Void> StartHandler(StartTimeInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Received start event at time {0}", request.StartTime);
+                await _driverBridge.DispatchStartEventAsync(new BridgeDriverStarted(new DateTime(request.StartTime)));
+                _receivedStartEvent = true;
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS4014:Await.Warning")]
+        public override async Task<ExceptionInfo> StopHandler(StopTimeInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Received stop event at time {0}", request.StopTime);
+                await _driverBridge.DispatchStopEvent(new BridgeDriverStopped(new DateTime(request.StopTime)));
+            }
+            catch (Exception ex)
+            {
+                Logger.Log(Level.Error, "Driver stop handler error", ex);
+                return GrpcUtils.SerializeException(ex);
+            }
+            finally
+            {
+                /* Do not await on shutdown async, which will cause a deadlock since
+                 * shutdown waits for this method to return.*/
+                _server.ShutdownAsync();
+            }
+            Logger.Log(Level.Info, "Clean stop handler execution");
+            return new ExceptionInfo()
+            {
+                NoError = true
+            };
+        }
+
+        public override async Task<Void> ActiveContextHandler(ContextInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Active context event id {0}", request.ContextId);
+                var activeContext = GetOrCreateActiveContext(request);
+                await _driverBridge.DispatchActiveContextEvent(activeContext);
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> ClosedContextHandler(ContextInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Closed context event id {0}", request.ContextId);
+                await _driverBridge.DispatchClosedContextEvent(CreateClosedContextAndForget(request));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> ContextMessageHandler(ContextMessageInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Context message event id {0}", request.ContextId);
+                await _driverBridge.DispatchContextMessageEvent(
+                    new BridgeContextMessage(
+                        request.ContextId,
+                        request.MessageSourceId,
+                        request.Payload.ToByteArray()));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> FailedContextHandler(ContextInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Failed context event id {0}", request.ContextId);
+                BridgeActiveContext activeContext;
+                BridgeActiveContext parentContext = null;
+                lock (_lock)
+                {
+                    if (_activeContexts.TryGetValue(request.ContextId, out activeContext))
+                    {
+                        _activeContexts.Remove(request.ContextId);
+                        parentContext = activeContext.ParentId.IsPresent()
+                            ? _activeContexts[activeContext.ParentId.Value]
+                            : null;
+                    }
+                }
+
+                if (activeContext != null)
+                {
+                    await _driverBridge.DispatchFailedContextEvent(
+                        new BridgeFailedContext(
+                            activeContext.Id,
+                            activeContext.EvaluatorId,
+                            CreateEvaluatorDescriptor(request.EvaluatorDescriptorInfo),
+                            Optional<IActiveContext>.OfNullable(parentContext)));
+                }
+                else
+                {
+                    Logger.Log(Level.Error, "unknown failed context {0}", request.ContextId);
+                }
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        // Evaluator handlers
+
+        public override async Task<Void> AllocatedEvaluatorHandler(EvaluatorInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Allocated evaluator id {0}", request.EvaluatorId);
+                var evaluatorDescriptor = CreateEvaluatorDescriptor(request.DescriptorInfo);
+                await _driverBridge.DispatchAllocatedEvaluatorEventAsync(
+                    new BridgeAllocatedEvaluator(request.EvaluatorId, _driverServiceClient, evaluatorDescriptor));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> CompletedEvaluatorHandler(EvaluatorInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Completed evaluator id {0}", request.EvaluatorId);
+                await _driverBridge.DispatchCompletedEvaluatorEvent(new BridgeCompletedEvaluator(request.EvaluatorId));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> FailedEvaluatorHandler(EvaluatorInfo info, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Failed evaluator id {0}", info.EvaluatorId);
+                await _driverBridge.DispatchFailedEvaluatorEvent(CreateFailedEvaluator(info));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        #region Task handlers
+
+        public override async Task<Void> RunningTaskHandler(TaskInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Running task {0}", request.TaskId);
+                var task = GetOrCreateRunningTask(request);
+                Logger.Log(Level.Info, "Dispatch running task {0}", task.Id);
+                await _driverBridge.DispatchRunningTaskEvent(task);
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> CompletedTaskHandler(TaskInfo request, ServerCallContext context)
+        {
+            try
+            {
+                lock (_lock)
+                {
+                    Logger.Log(Level.Info, "Completed task {0}", request.TaskId);
+                    _runningTasks.Remove(request.TaskId);
+                }
+                var activeContext = GetOrCreateActiveContext(request.Context);
+                await _driverBridge.DispatchCompletedTaskEvent(new BridgeCompletedTask(request.Result.ToByteArray(),
+                    request.TaskId,
+                    activeContext));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> FailedTaskHandler(TaskInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Failed task {0}", request.TaskId);
+                var failedTask = CreateFailedTaskAndForget(request.TaskId, request.Exception,
+                    Optional<IActiveContext>.OfNullable(GetOrCreateActiveContext(request.Context)));
+                Logger.Log(Level.Info, "Dispatch failed task {0}", request.TaskId);
+                await _driverBridge.DispatchFailedTaskEvent(failedTask);
+            }
+            catch (Exception ex)
+            {
+                Logger.Log(Level.Warning, "Failed task exception", ex);
+                _bridgeClock.Dispose(ex);
+            }
+            Logger.Log(Level.Info, "Done with failed task handler");
+            return Void;
+        }
+
+        public override async Task<Void> TaskMessageHandler(TaskMessageInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Message from task {0}", request.TaskId);
+                await _driverBridge.DispatchTaskMessageEvent(new BridgeTaskMessage(request.Payload.ToByteArray(),
+                    request.TaskId,
+                    request.MessageSourceId));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> SuspendedTaskHandler(TaskInfo request, ServerCallContext context)
+        {
+            try
+            {
+                Logger.Log(Level.Info, "Suspended task {0}", request.TaskId);
+                var activeContext = GetOrCreateActiveContext(request.Context);
+                await _driverBridge.DispatchSuspendedTaskEvent(new BridgeSuspendedTask(request.Result.ToByteArray(),
+                    request.TaskId,
+                    activeContext));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        #endregion Task handlers
+
+        #region Client handlers
+
+        public override async Task<Void> ClientCloseHandler(Void request, ServerCallContext context)
+        {
+            try
+            {
+                await _driverBridge.DispatchClientCloseEvent();
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> ClientCloseWithMessageHandler(ClientMessageInfo request, ServerCallContext context)
+        {
+            try
+            {
+                await _driverBridge.DispatchClientCloseWithMessageEvent(request.Payload.ToByteArray());
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> ClientMessageHandler(ClientMessageInfo request, ServerCallContext context)
+        {
+            try
+            {
+                await _driverBridge.DispatchClientMessageEvent(request.Payload.ToByteArray());
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        #endregion Client handlers
+
+        #region Driver Restart Handlers
+
+        public override async Task<Void> DriverRestartHandler(DriverRestartInfo request, ServerCallContext context)
+        {
+            try
+            {
+                ISet<string> expectedEvaluatorIds = new HashSet<string>(request.ExpectedEvaluatorIds);
+                await _driverBridge.DispatchDriverRestartedEvent(new BridgeDriverRestarted(
+                    new DateTime(request.StartTime.StartTime),
+                    expectedEvaluatorIds,
+                    (int)request.ResubmissionAttempts));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> DriverRestartActiveContextHandler(ContextInfo request, ServerCallContext context)
+        {
+            try
+            {
+                var activeContext = GetOrCreateActiveContext(request);
+                await _driverBridge.DispatchDriverRestartActiveContextEvent(activeContext);
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> DriverRestartRunningTaskHandler(TaskInfo request, ServerCallContext context)
+        {
+            try
+            {
+                var runningTask = GetOrCreateRunningTask(request);
+                await _driverBridge.DispatchDriverRestartRunningTaskEvent(runningTask);
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+
+            return Void;
+        }
+
+        public override async Task<Void> DriverRestartCompletedHandler(DriverRestartCompletedInfo request, ServerCallContext context)
+        {
+            try
+            {
+                await _driverBridge.DispatchDriverRestartCompletedEvent(
+                    new BridgeDriverRestartCompleted(new DateTime(request.CompletionTime.StopTime),
+                        request.IsTimedOut));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        public override async Task<Void> DriverRestartFailedEvaluatorHandler(EvaluatorInfo request, ServerCallContext context)
+        {
+            try
+            {
+                await _driverBridge.DispatchDriverRestartFailedEvaluatorEvent(CreateFailedEvaluator(request));
+            }
+            catch (Exception ex)
+            {
+                _bridgeClock.Dispose(ex);
+            }
+            return Void;
+        }
+
+        #endregion Driver Restart Handlers
+
+        #region helper methods
+
+        private BridgeActiveContext GetOrCreateActiveContext(ContextInfo info)
+        {
+            lock (_lock)
+            {
+                if (_activeContexts.TryGetValue(info.ContextId, out BridgeActiveContext context))
+                {
+                    Logger.Log(Level.Verbose, "Context already exists, use it: {0}", info.ContextId);
+                    return context;
+                }
+
+                Logger.Log(Level.Verbose, "Create active context {0}", info.ContextId);
+
+                context = new BridgeActiveContext(
+                    _driverServiceClient,
+                    info.ContextId,
+                    info.EvaluatorId,
+                    Optional<string>.OfNullable(info.ParentId.Length == 0 ? null : info.ParentId),
+                    CreateEvaluatorDescriptor(info.EvaluatorDescriptorInfo));
+
+                _activeContexts.Add(info.ContextId, context);
+
+                return context;
+            }
+        }
+
+        private BridgeRunningTask GetOrCreateRunningTask(TaskInfo task)
+        {
+            lock (_lock)
+            {
+                if (_runningTasks.TryGetValue(task.TaskId, out BridgeRunningTask runningTask))
+                {
+                    return runningTask;
+                }
+                var activeContext = GetOrCreateActiveContext(task.Context);
+                runningTask = new BridgeRunningTask(_driverServiceClient, task.TaskId, activeContext);
+                _runningTasks[task.TaskId] = runningTask;
+                return runningTask;
+            }
+        }
+
+        private BridgeFailedTask CreateFailedTaskAndForget(string taskId, ExceptionInfo info, Optional<IActiveContext> context)
+        {
+            lock (_lock)
+            {
+                if (_runningTasks.TryGetValue(taskId, out BridgeRunningTask task))
+                {
+                    Logger.Log(Level.Info, "Create failed task {0}", taskId);
+                    _runningTasks.Remove(taskId);
+                    return new BridgeFailedTask(
+                        Optional<IActiveContext>.Of(task.ActiveContext),
+                        task.Id,
+                        info.Message,
+                        info.Data.ToByteArray());
+                }
+                else
+                {
+                    Logger.Log(Level.Warning, "Create unknown failed task {0} with data {1}",
+                        taskId, !info.Data.IsEmpty);
+                    return new BridgeFailedTask(
+                        context,
+                        taskId,
+                        info.Message,
+                        info.Data.ToByteArray());
+                }
+            }
+        }
+
+        private BridgeFailedContext CreateFailedContextAndForget(EvaluatorInfo info, string contextId)
+        {
+            lock (_lock)
+            {
+                var evaluatorId = info.EvaluatorId;
+                if (_activeContexts.TryGetValue(contextId, out BridgeActiveContext activeContext))
+                {
+                    _activeContexts.Remove(contextId);
+                    var parentContext = activeContext.ParentId.IsPresent()
+                        ? _activeContexts[activeContext.ParentId.Value]
+                        : null;
+                    return new BridgeFailedContext(contextId,
+                        evaluatorId,
+                        activeContext.EvaluatorDescriptor,
+                        Optional<IActiveContext>.OfNullable(parentContext));
+                }
+                else
+                {
+                    return new BridgeFailedContext(contextId,
+                        evaluatorId,
+                        CreateEvaluatorDescriptor(info.DescriptorInfo),
+                        Optional<IActiveContext>.Empty());
+                }
+            }
+        }
+
+        private BridgeClosedContext CreateClosedContextAndForget(ContextInfo request)
+        {
+            lock (_lock)
+            {
+                if (_activeContexts.TryGetValue(request.ContextId, out BridgeActiveContext activeContext))
+                {
+                    _activeContexts.Remove(request.ContextId);
+                    var parentContext = _activeContexts[activeContext.ParentId.Value];
+                    return new BridgeClosedContext(
+                        activeContext.Id,
+                        activeContext.EvaluatorId,
+                        Optional<string>.Of(parentContext.Id),
+                        CreateEvaluatorDescriptor(request.EvaluatorDescriptorInfo),
+                        parentContext);
+                }
+                else
+                {
+                    Logger.Log(Level.Error, "Unknown context {0}", request.ContextId);
+                    return new BridgeClosedContext(
+                        request.ContextId,
+                        request.EvaluatorId,
+                        Optional<string>.Empty(),
+                        CreateEvaluatorDescriptor(request.EvaluatorDescriptorInfo),
+                        null);
+                }
+            }
+        }
+
+        private BridgeFailedEvaluator CreateFailedEvaluator(EvaluatorInfo info)
+        {
+            try
+            {
+                var failedContexts = info.Failure.FailedContexts.Select(contextId =>
+                    CreateFailedContextAndForget(info, contextId)).Cast<IFailedContext>().ToList();
+                var failedTask = string.IsNullOrEmpty(info.Failure.FailedTaskId)
+                    ? Optional<IFailedTask>.Empty()
+                    : Optional<IFailedTask>.Of(CreateFailedTaskAndForget(info.Failure.FailedTaskId,
+                        info.Failure.Exception,
+                        Optional<IActiveContext>.Empty()));
+
+                return new BridgeFailedEvaluator(
+                    info.EvaluatorId,
+                    CreateEvaluatorException(info),
+                    failedContexts,
+                    failedTask);
+            }
+            catch (Exception ex)
+            {
+                Logger.Log(Level.Error, "could not create failed evaluator", ex);
+                throw;
+            }
+        }
+
+        private static EvaluatorException CreateEvaluatorException(EvaluatorInfo eval)
+        {
+            var failureInfo = eval.Failure;
+            var errorBytes = failureInfo.Exception.Data.ToByteArray();
+            if (errorBytes == null || errorBytes.Length == 0)
+            {
+                Logger.Log(Level.Error, "Exception without object details: {0}", failureInfo.Exception.Message);
+                return new EvaluatorException(
+                    eval.EvaluatorId,
+                    failureInfo.Exception.Message,
+                    string.Join(";", failureInfo.Exception.StackTrace));
+            }
+            // When the Exception originates from the C# side.
+            Exception inner;
+            try
+            {
+                inner = (Exception)ByteUtilities.DeserializeFromBinaryFormat(errorBytes);
+            }
+            catch (SerializationException se)
+            {
+                inner = NonSerializableEvaluatorException.UnableToDeserialize(
+                    "Exception from Evaluator was not able to be deserialized, returning a NonSerializableEvaluatorException.",
+                    se);
+            }
+            return new EvaluatorException(eval.EvaluatorId, inner.Message, inner);
+        }
+
+        private static IEvaluatorDescriptor CreateEvaluatorDescriptor(EvaluatorDescriptorInfo descriptorInfo)
+        {
+            var runtimeName = RuntimeName.Local;
+            if (!string.IsNullOrWhiteSpace(descriptorInfo.RuntimeName) &&
+                !Enum.TryParse(descriptorInfo.RuntimeName, true, out runtimeName))
+            {
+                throw new ArgumentException($"Unknown runtime name received {descriptorInfo.RuntimeName}");
+            }
+
+            if (descriptorInfo.NodeDescriptorInfo == null)
+            {
+                Logger.Log(Level.Warning, "Node Descriptor not present in Evalautor Descriptor");
+                return null;
+            }
+            var nodeDescriptor = new NodeDescriptor(
+                descriptorInfo.NodeDescriptorInfo.IpAddress,
+                descriptorInfo.NodeDescriptorInfo.Port,
+                descriptorInfo.NodeDescriptorInfo.HostName,
+                new CPU(descriptorInfo.Cores),
+                new RAM(descriptorInfo.Memory));
+            return new EvaluatorDescriptor(nodeDescriptor, descriptorInfo.Memory, descriptorInfo.Cores, runtimeName);
+        }
+
+        #endregion helper methods
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverServiceClient.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverServiceClient.cs
new file mode 100644
index 0000000..bc43e33
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverServiceClient.cs
@@ -0,0 +1,261 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Google.Protobuf;
+using Grpc.Core;
+using Org.Apache.REEF.Bridge.Core.Common.Driver;
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Driver
+{
+    internal class DriverServiceClient : IDriverServiceClient
+    {
+        private static readonly Logger Logger = Logger.GetLogger(typeof(DriverServiceClient));
+
+        private readonly IConfigurationSerializer _configurationSerializer;
+
+        private readonly DriverService.DriverServiceClient _driverServiceStub;
+
+        [Inject]
+        private DriverServiceClient(
+            IConfigurationSerializer configurationSerializer,
+            [Parameter(Value = typeof(DriverServicePort))] int driverServicePort)
+        {
+            _configurationSerializer = configurationSerializer;
+            Logger.Log(Level.Info, "Binding to driver service at port {0}", driverServicePort);
+            var driverServiceChannel = new Channel("127.0.0.1", driverServicePort, ChannelCredentials.Insecure);
+            _driverServiceStub = new DriverService.DriverServiceClient(driverServiceChannel);
+            Logger.Log(Level.Info, "Channel state {0}", driverServiceChannel.State);
+        }
+
+        public void RegisterDriverClientService(Exception exception)
+        {
+            Logger.Log(Level.Info, "Register driver client error", exception);
+            var registration = new DriverClientRegistration
+            {
+                Exception = GrpcUtils.SerializeException(exception)
+            };
+            _driverServiceStub.RegisterDriverClient(registration);
+        }
+
+        public void RegisterDriverClientService(string host, int port)
+        {
+            Logger.Log(Level.Info, "Register driver client at host {0} port {1}", host, port);
+            var registration = new DriverClientRegistration
+            {
+                Host = host,
+                Port = port
+            };
+            _driverServiceStub.RegisterDriverClient(registration);
+        }
+
+        public void OnShutdown()
+        {
+            Logger.Log(Level.Info, "Driver clean shutdown");
+            _driverServiceStub.Shutdown(new ShutdownRequest());
+        }
+
+        public void OnShutdown(Exception ex)
+        {
+            Logger.Log(Level.Error, "Driver shutdown with error", ex);
+            byte[] errorBytes;
+            try
+            {
+                errorBytes = ByteUtilities.SerializeToBinaryFormat(ex);
+            }
+            catch (SerializationException se)
+            {
+                Logger.Log(Level.Warning, "Unable to serialize exception", ex);
+                errorBytes = ByteUtilities.SerializeToBinaryFormat(
+                    NonSerializableJobException.UnableToSerialize(ex, se));
+            }
+
+            _driverServiceStub.Shutdown(new ShutdownRequest()
+            {
+                Exception = new ExceptionInfo()
+                {
+                    NoError = false,
+                    Message = ex.Message,
+                    Name = ex.Source,
+                    Data = ByteString.CopyFrom(errorBytes)
+                }
+            });
+        }
+
+        public void OnSetAlarm(string alarmId, long timeoutMs)
+        {
+            _driverServiceStub.SetAlarm(new AlarmRequest()
+            {
+                AlarmId = alarmId,
+                TimeoutMs = (int)timeoutMs
+            });
+        }
+
+        public void OnEvaluatorRequest(IEvaluatorRequest evaluatorRequest)
+        {
+            var request = new ResourceRequest()
+            {
+                ResourceCount = evaluatorRequest.Number,
+                Cores = evaluatorRequest.VirtualCore,
+                MemorySize = evaluatorRequest.MemoryMegaBytes,
+                RelaxLocality = evaluatorRequest.RelaxLocality,
+                RuntimeName = evaluatorRequest.RuntimeName,
+                NodeLabel = evaluatorRequest.NodeLabelExpression
+            };
+            if (!string.IsNullOrEmpty(evaluatorRequest.Rack))
+            {
+                request.RackNameList.Add(evaluatorRequest.Rack);
+            }
+            request.NodeNameList.Add(evaluatorRequest.NodeNames);
+            _driverServiceStub.RequestResources(request);
+        }
+
+        public void OnEvaluatorClose(string evalautorId)
+        {
+            _driverServiceStub.AllocatedEvaluatorOp(new AllocatedEvaluatorRequest()
+            {
+                EvaluatorId = evalautorId,
+                CloseEvaluator = true
+            });
+        }
+
+        public void OnEvaluatorSubmit(
+            string evaluatorId,
+            IConfiguration contextConfiguration,
+            Optional<IConfiguration> serviceConfiguration,
+            Optional<IConfiguration> taskConfiguration,
+            List<FileInfo> addFileList, List<FileInfo> addLibraryList)
+        {
+            Logger.Log(Level.Info, "Submitting allocated evaluator {0}", evaluatorId);
+
+            var evaluatorConf =
+                _configurationSerializer.ToString(TangFactory.GetTang().NewConfigurationBuilder().Build());
+            var contextConf = _configurationSerializer.ToString(contextConfiguration);
+            var serviceConf = !serviceConfiguration.IsPresent()
+                ? string.Empty
+                : _configurationSerializer.ToString(serviceConfiguration.Value);
+            var taskConf = !taskConfiguration.IsPresent()
+                ? string.Empty
+                : _configurationSerializer.ToString(taskConfiguration.Value);
+            var request = new AllocatedEvaluatorRequest()
+            {
+                EvaluatorId = evaluatorId,
+                EvaluatorConfiguration = evaluatorConf,
+                ServiceConfiguration = serviceConf,
+                ContextConfiguration = contextConf,
+                TaskConfiguration = taskConf,
+                SetProcess = new AllocatedEvaluatorRequest.Types.EvaluatorProcessRequest()
+                {
+                    ProcessType = AllocatedEvaluatorRequest.Types.EvaluatorProcessRequest.Types.Type.Dotnet
+                }
+            };
+            request.AddFiles.Add(addFileList.Select(f => f.ToString()));
+            request.AddLibraries.Add(addLibraryList.Select(f => f.ToString()));
+            _driverServiceStub.AllocatedEvaluatorOp(request);
+        }
+
+        public void OnContextClose(string contextId)
+        {
+            Logger.Log(Level.Info, "Close context {0}", contextId);
+            _driverServiceStub.ActiveContextOp(new ActiveContextRequest()
+            {
+                ContextId = contextId,
+                CloseContext = true
+            });
+        }
+
+        public void OnContextSubmitContext(string contextId, IConfiguration contextConfiguration)
+        {
+            _driverServiceStub.ActiveContextOp(new ActiveContextRequest()
+            {
+                ContextId = contextId,
+                NewContextRequest = _configurationSerializer.ToString(contextConfiguration)
+            });
+        }
+
+        public void OnContextSubmitTask(string contextId, IConfiguration taskConfiguration)
+        {
+            _driverServiceStub.ActiveContextOp(new ActiveContextRequest()
+            {
+                ContextId = contextId,
+                NewTaskRequest = _configurationSerializer.ToString(taskConfiguration)
+            });
+        }
+
+        public void OnContextMessage(string contextId, byte[] message)
+        {
+            _driverServiceStub.ActiveContextOp(new ActiveContextRequest()
+            {
+                ContextId = contextId,
+                Message = ByteString.CopyFrom(message)
+            });
+        }
+
+        public void OnTaskSuspend(string taskId, Optional<byte[]> message)
+        {
+            var op = new RunningTaskRequest()
+            {
+                TaskId = taskId,
+                Operation = RunningTaskRequest.Types.Operation.Suspend
+            };
+            if (message.IsPresent())
+            {
+                op.Message = ByteString.CopyFrom(message.Value);
+            }
+
+            _driverServiceStub.RunningTaskOp(op);
+        }
+
+        public void OnTaskClose(string taskId, Optional<byte[]> message)
+        {
+            var op = new RunningTaskRequest()
+            {
+                TaskId = taskId,
+                Operation = RunningTaskRequest.Types.Operation.Close
+            };
+            if (message.IsPresent())
+            {
+                op.Message = ByteString.CopyFrom(message.Value);
+            }
+
+            _driverServiceStub.RunningTaskOp(op);
+        }
+
+        public void OnTaskMessage(string taskId, byte[] message)
+        {
+            _driverServiceStub.RunningTaskOp(new RunningTaskRequest()
+            {
+                TaskId = taskId,
+                Message = ByteString.CopyFrom(message),
+                Operation = RunningTaskRequest.Types.Operation.SendMessage
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverServicePort.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverServicePort.cs
new file mode 100644
index 0000000..e22e1d7
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/DriverServicePort.cs
@@ -0,0 +1,29 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Driver
+{
+    /// <summary>
+    /// Driver serivce port represents the Java driver server port
+    /// that clients should connect to.
+    /// </summary>
+    [NamedParameter(documentation: "the driver service port")]
+    public sealed class DriverServicePort : Name<int>
+    {
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/GRPCUtils.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/GRPCUtils.cs
new file mode 100644
index 0000000..d0efea5
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Driver/GRPCUtils.cs
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Google.Protobuf;
+using Org.Apache.REEF.Bridge.Core.Proto;
+using Org.Apache.REEF.Common.Exceptions;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Grpc.Driver
+{
+    internal static class GrpcUtils
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(GrpcUtils));
+
+        public static ExceptionInfo SerializeException(Exception ex)
+        {
+            ByteString serializedException;
+            try
+            {
+                serializedException = ByteString.CopyFrom(ByteUtilities.SerializeToBinaryFormat(ex));
+            }
+            catch (SerializationException se)
+            {
+                Log.Log(Level.Warning, "Unable to serialize exception", ex);
+                serializedException = ByteString.CopyFrom(ByteUtilities.SerializeToBinaryFormat(
+                    NonSerializableJobException.UnableToSerialize(ex, se)));
+            }
+            return new ExceptionInfo()
+            {
+                NoError = false,
+                Name = ex.GetType().ToString(),
+                Message = ex.Message,
+                Data = serializedException
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Org.Apache.REEF.Bridge.Core.Grpc.csproj b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Org.Apache.REEF.Bridge.Core.Grpc.csproj
new file mode 100644
index 0000000..914df3c
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Grpc/Org.Apache.REEF.Bridge.Core.Grpc.csproj
@@ -0,0 +1,44 @@
+<Project>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (thee
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+  <PropertyGroup>
+    <AssemblyName>Org.Apache.REEF.Bridge.Core.Grpc</AssemblyName>
+    <Description>Client for REEF.NET Bridge Core</Description>
+    <PackageTags>REEF Bridge Core Grpc</PackageTags>
+    <!-- Disable default embedded resources as we override this in the project -->
+    <EnableDefaultEmbeddedResourceItems>False</EnableDefaultEmbeddedResourceItems>
+  </PropertyGroup>
+  <Import Project="..\build.Library.props" />
+
+  <ItemGroup>
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Common\Org.Apache.REEF.Bridge.Core.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Proto\Org.Apache.REEF.Bridge.Core.Proto.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Utilities\Org.Apache.REEF.Utilities.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Tang\Org.Apache.REEF.Tang.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Driver\Org.Apache.REEF.Driver.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Network\Org.Apache.REEF.Network.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Wake\Org.Apache.REEF.Wake.csproj" />
+  </ItemGroup>
+  <Import Project="..\build.targets" />
+    
+  <ItemGroup>
+    <EmbeddedResource Include="$(BinDir)$(Configuration)\Org.Apache.REEF.Bridge.JAR\netstandard2.0\*.jar" />
+  </ItemGroup>
+</Project>
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/FailedTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/FailedTask.cs
new file mode 100644
index 0000000..749098a
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/FailedTask.cs
@@ -0,0 +1,44 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.HelloREEF
+{
+    /// <summary>
+    /// A Task that merely prints a greeting and exits.
+    /// </summary>
+    public sealed class FailedTask : ITask
+    {
+        [Inject]
+        private FailedTask()
+        {
+        }
+
+        public void Dispose()
+        {
+            Console.WriteLine("Disposed.");
+        }
+
+        public byte[] Call(byte[] memento)
+        {
+            throw new IllegalStateException("Hello, Failed REEF Task!");
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloDriver.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloDriver.cs
new file mode 100644
index 0000000..86a43f0
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloDriver.cs
@@ -0,0 +1,133 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.HelloREEF
+{
+    /// <summary>
+    /// The Driver for HelloREEF: It requests a single Evaluator and then submits the HelloTask to it.
+    /// </summary>
+    public sealed class HelloDriver :
+        IObserver<IAllocatedEvaluator>,
+        IObserver<IFailedEvaluator>,
+        IObserver<ICompletedEvaluator>,
+        IObserver<IDriverStarted>,
+        IObserver<IDriverStopped>,
+        IObserver<IRunningTask>,
+        IObserver<IActiveContext>,
+        IObserver<ICompletedTask>,
+        IObserver<IFailedTask>
+    {
+        private static readonly Logger Logger = Logger.GetLogger(typeof(HelloDriver));
+        private readonly IEvaluatorRequestor _evaluatorRequestor;
+
+        [Inject]
+        private HelloDriver(IEvaluatorRequestor evaluatorRequestor)
+        {
+            _evaluatorRequestor = evaluatorRequestor;
+        }
+
+        /// <summary>
+        /// Submits the HelloTask to the Evaluator.
+        /// </summary>
+        /// <param name="allocatedEvaluator">Newly allocated evaluator's proxy object.</param>
+        public void OnNext(IAllocatedEvaluator allocatedEvaluator)
+        {
+            Logger.Log(Level.Info, "Evaluator allocated: {0}", allocatedEvaluator);
+
+            var taskConfiguration = TaskConfiguration.ConfigurationModule
+                .Set(TaskConfiguration.Identifier, "HelloTask")
+                .Set(TaskConfiguration.Task, GenericType<HelloTask>.Class)
+                .Build();
+
+            Logger.Log(Level.Verbose, "Submit task: {0}", taskConfiguration);
+            allocatedEvaluator.SubmitTask(taskConfiguration);
+        }
+
+        public void OnNext(IFailedEvaluator value)
+        {
+            Logger.Log(Level.Info, "Failed Evaluator: {0}", value.Id);
+            throw value.EvaluatorException;
+        }
+
+        public void OnNext(ICompletedEvaluator value)
+        {
+            Logger.Log(Level.Info, "Completed Evaluator: {0}", value.Id);
+        }
+
+        public void OnError(Exception error)
+        {
+            throw error;
+        }
+
+        public void OnCompleted()
+        {
+        }
+
+        public void OnNext(IDriverStopped value)
+        {
+            Logger.Log(Level.Info, "HelloDriver stopped at {0}", value.StopTime);
+        }
+
+        /// <summary>
+        /// Called to start the user mode driver.
+        /// </summary>
+        /// <param name="driverStarted">Notification that the Driver is up and running.</param>
+        public void OnNext(IDriverStarted driverStarted)
+        {
+            Logger.Log(Level.Info, "HelloDriver started at {0}", driverStarted.StartTime);
+            _evaluatorRequestor.Submit(_evaluatorRequestor.NewBuilder().SetMegabytes(64).Build());
+        }
+
+        public void OnNext(IRunningTask value)
+        {
+            Logger.Log(Level.Info, "HelloDriver received running task {0}", value.Id);
+        }
+
+        public void OnNext(ICompletedTask value)
+        {
+            Logger.Log(Level.Info, "HelloDriver received completed task {0}", value.Id);
+            var taskConfiguration = TaskConfiguration.ConfigurationModule
+                .Set(TaskConfiguration.Identifier, "FailedTask")
+                .Set(TaskConfiguration.Task, GenericType<FailedTask>.Class)
+                .Build();
+            value.ActiveContext.SubmitTask(taskConfiguration);
+        }
+
+        public void OnNext(IFailedTask value)
+        {
+            Logger.Log(Level.Info, "HelloDriver received failed task {0} with active context {1}", 
+                value.Id, value.GetActiveContext().Value.Id);
+            value.GetActiveContext().Value.Dispose();
+            Logger.Log(Level.Info, "HelloDriver closed active context {0}", value.GetActiveContext().Value.Id);
+        }
+
+        public void OnNext(IActiveContext value)
+        {
+            Logger.Log(Level.Info, "HelloDriver received active context {0}", value.Id);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloREEF.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloREEF.cs
new file mode 100644
index 0000000..4ebd6f1
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloREEF.cs
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config;
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime;
+using Org.Apache.REEF.Bridge.Core.Grpc.Client;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Globalization;
+
+namespace Org.Apache.REEF.Bridge.Core.HelloREEF
+{
+    /// <summary>
+    /// A Tool that submits HelloREEFDriver for execution.
+    /// </summary>
+    public sealed class HelloREEF
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(HelloREEF));
+
+        private const string Local = "local";
+        private const string YARN = "yarn";
+        private const string HDInsight = "hdi";
+        private const string AzureBatch = "azurebatch";
+
+        [Inject]
+        private HelloREEF()
+        {
+        }
+
+        /// <summary>
+        /// Runs HelloREEF using the IREEFClient passed into the constructor.
+        /// </summary>
+        private void Run(string runtime)
+        {
+            // The driver configuration contains all the needed bindings.
+            var helloDriverConfiguration = DriverApplicationConfiguration.ConfigurationModule
+                .Set(DriverApplicationConfiguration.OnDriverStarted, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnDriverStopped, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorAllocated, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorCompleted, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorFailed, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnContextActive, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskRunning, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskCompleted, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskFailed, GenericType<HelloDriver>.Class)
+                .Set(DriverApplicationConfiguration.CustomTraceLevel, Level.Verbose.ToString())
+                .Build();
+
+            var applicationId = GetApplicationId();
+
+            // The JobSubmission contains the Driver configuration as well as the files needed on the Driver.
+            var driverRuntimeConfiguration = DriverRuntimeConfiguration.ConfigurationModule
+                .Set(DriverRuntimeConfiguration.OsType, GenericType<OsLinux>.Class)
+                .Set(DriverRuntimeConfiguration.JobId, applicationId);
+            driverRuntimeConfiguration = DriverRuntimeConfiguration.AddGlobalAssemblyForType(driverRuntimeConfiguration, typeof(HelloDriver));
+
+            var runtimeConfiguration = GetRuntimeConfiguration(runtime);
+
+            using (var launcher = ClientLauncherFactory.GetLauncher(runtimeConfiguration, driverRuntimeConfiguration.Build()))
+            {
+                var launcherStatus = launcher.SubmitAsync(helloDriverConfiguration).Result;
+                Log.Log(Level.Info, "Final Launch Status {0}", launcherStatus);
+                if (launcherStatus.Error.IsPresent())
+                {
+                    throw launcherStatus.Error.Value;
+                }
+            }
+        }
+
+        private string GetApplicationId()
+        {
+            return "HelloWorldJob-" + DateTime.Now.ToString("ddd-MMM-d-HH-mm-ss-yyyy", CultureInfo.CreateSpecificCulture("en-US"));
+        }
+
+        /// <summary>
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        private static IConfiguration GetRuntimeConfiguration(string name)
+        {
+            switch (name)
+            {
+                case Local:
+                    return LocalRuntimeConfiguration.ConfigurationModule
+                        .Set(LocalRuntimeConfiguration.NumberOfEvaluators, "2")
+                        .Build();
+
+                case YARN:
+                    return YarnRuntimeConfiguration.ConfigurationModule.Build();
+
+                case HDInsight:
+                    // To run against HDInsight please replace placeholders below, with actual values for
+                    // connection string, container name (available at Azure portal) and HDInsight
+                    // credentials (username and password)
+                    const string connectionString = "ConnString";
+                    const string continerName = "foo";
+                    return HdInsightRuntimeConfiguration.ConfigurationModule
+                        .Set(HdInsightRuntimeConfiguration.HdInsightPassword, @"pwd")
+                        .Set(HdInsightRuntimeConfiguration.HdInsightUserName, @"foo")
+                        .Set(HdInsightRuntimeConfiguration.HdInsightUrl, @"https://foo.azurehdinsight.net/")
+                        .Build();
+
+                case AzureBatch:
+                    return AzureBatchRuntimeConfiguration.ConfigurationModule
+                        .Set(AzureBatchRuntimeConfiguration.AzureBatchAccountKey, "###")
+                        .Set(AzureBatchRuntimeConfiguration.AzureBatchAccountName, "###")
+                        .Set(AzureBatchRuntimeConfiguration.AzureBatchAccountUri, "###")
+                        .Set(AzureBatchRuntimeConfiguration.AzureBatchPoolId, "###")
+                        .Set(AzureBatchRuntimeConfiguration.AzureStorageAccountKey, "###")
+                        .Set(AzureBatchRuntimeConfiguration.AzureStorageAccountName, "###")
+                        .Set(AzureBatchRuntimeConfiguration.AzureStorageContainerName, "###")
+                        .Build();
+
+                default:
+                    throw new Exception("Unknown runtime: " + name);
+            }
+        }
+
+        public static void MainSimple(string[] args)
+        {
+            var runtime = args.Length > 0 ? args[0] : Local;
+
+            // Execute the HelloREEF, with these parameters injected
+            TangFactory.GetTang()
+                .NewInjector()
+                .GetInstance<HelloREEF>()
+                .Run(runtime);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloTask.cs
new file mode 100644
index 0000000..15aae34
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/HelloTask.cs
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.HelloREEF
+{
+    /// <summary>
+    /// A Task that merely prints a greeting and exits.
+    /// </summary>
+    public sealed class HelloTask : ITask
+    {
+        [Inject]
+        private HelloTask()
+        {
+        }
+
+        public void Dispose()
+        {
+            Console.WriteLine("Disposed.");
+        }
+
+        public byte[] Call(byte[] memento)
+        {
+            Console.WriteLine("Hello, REEF!");
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/Org.Apache.REEF.Bridge.Core.HelloREEF.csproj b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/Org.Apache.REEF.Bridge.Core.HelloREEF.csproj
new file mode 100644
index 0000000..6af8bc2
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/Org.Apache.REEF.Bridge.Core.HelloREEF.csproj
@@ -0,0 +1,45 @@
+<Project>
+  <!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+  <PropertyGroup>
+    <AssemblyName>Org.Apache.REEF.Bridge.Core.HelloREEF</AssemblyName>
+    <Description>Hello World Example for REEF.NET Bridge Core</Description>
+  </PropertyGroup>
+  <Import Project="..\build.App.props" />
+
+<ItemGroup>
+    <None Include="$(SolutionDir)App.config">
+      <Link>App.config</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+</ItemGroup>
+  <ItemGroup>
+	<ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Grpc\Org.Apache.REEF.Bridge.Core.Grpc.csproj" />
+	<ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Driver\Org.Apache.REEF.Bridge.Core.Driver.csproj" PrivateAssets="none" />
+	<ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Common\Org.Apache.REEF.Bridge.Core.Common.csproj" />
+	<ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Proto\Org.Apache.REEF.Bridge.Core.Proto.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Evaluator\Org.Apache.REEF.Evaluator.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Tang\Org.Apache.REEF.Tang.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Utilities\Org.Apache.REEF.Utilities.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Wake\Org.Apache.REEF.Wake.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.IO\Org.Apache.REEF.IO.csproj" />
+  </ItemGroup>
+  <Import Project="..\build.targets" />
+</Project>
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/Run.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/Run.cs
new file mode 100644
index 0000000..37043ec
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.HelloREEF/Run.cs
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+namespace Org.Apache.REEF.Bridge.Core.HelloREEF
+{
+    public sealed class Run
+    {
+        /// <summary>
+        /// Program that runs hello reef
+        /// </summary>
+        /// <param name="args"></param>
+        public static void Main(string[] args)
+        {
+            HelloREEF.MainSimple(args);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Proto/Grpc.targets b/lang/cs/Org.Apache.REEF.Bridge.Core.Proto/Grpc.targets
new file mode 100644
index 0000000..ba3e113
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Proto/Grpc.targets
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<!-- GRPC CODE GENERATION TARGETS FOR MSBUILD -->
+<Project>
+  <ItemGroup>
+    <PackageReference Include="RoslynCodeTaskFactory" Version="2.0.7" />
+  </ItemGroup>
+  <UsingTask TaskName="GrpcToCSharp" TaskFactory="CodeTaskFactory" AssemblyFile="$(RoslynCodeTaskFactory)" Condition=" '$(RoslynCodeTaskFactory)' != '' ">
+    <ParameterGroup>
+      <!-- The directory where the project is located. This is typically $(ProjectDir) -->
+      <OutputDirectory ParameterType="System.String" Required="true" />
+      <!-- This is the list of C# target files to be generaterd. This is typically @(Compile) -->
+      <SourceFileList ParameterType="System.String" Required="true" />
+      <!-- The directory where the .avsc schema files are located. -->
+      <GrpcSchemaDirectory ParameterType="System.String" Required="true" />
+      <!-- The where gRPC schema generator and dependent libraries are located. -->
+      <GrpcBinaryDirectory ParameterType="System.String" Required="true" />
+      <!-- gRPC tools extension e.g., .exe for windows. -->
+      <GrpcToolsExtension ParameterType="System.String" Required="false" />
+    </ParameterGroup>
+    <Task>
+      <Using Namespace="System" />
+      <Using Namespace="System.IO" />
+      <Using Namespace="System.Diagnostics" />
+      <Using Namespace="System.Threading" />
+      <Using Namespace="System.Threading.Tasks" />
+      <Code Type="Fragment" Language="C#">
+        <![CDATA[
+          // Create a temporary working directory for the log file.
+          string tempDir = Path.GetFullPath(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
+          Directory.CreateDirectory(tempDir);
+
+          var grpcCSharpPlugin = "grpc_csharp_plugin";
+          var protocExe = "protoc";
+          if (GrpcToolsExtension != null)
+          {
+            grpcCSharpPlugin += GrpcToolsExtension;
+            protocExe += GrpcToolsExtension;
+          }
+          // Get the full path to the directory where the gRPC .proto files are located.
+          string grpcSrcFileDirectory = Path.GetFullPath(GrpcSchemaDirectory);
+          string grpcToolsDirectory = Path.GetFullPath(GrpcBinaryDirectory);
+          string grpcOutputDirectory = Path.GetFullPath(OutputDirectory);
+          string grpcPluginName = Path.Combine(GrpcBinaryDirectory, grpcCSharpPlugin);
+
+          Directory.CreateDirectory(grpcOutputDirectory);
+           
+          // Get the list of names of .proto files
+          string[] sourceFiles = SourceFileList.Split(';');
+
+          // Setup the conversion process.
+          ProcessStartInfo rProcInfo = new ProcessStartInfo()
+          {
+              RedirectStandardOutput = true,
+              RedirectStandardError = true,
+              UseShellExecute = false,
+              CreateNoWindow = true,
+              FileName = Path.Combine(grpcToolsDirectory, protocExe)
+          };
+
+          bool conversionError = false;
+          using (StreamWriter logWriter = new StreamWriter(Path.Combine(tempDir, "GrpcCodeGeneration.log")))
+          {
+              foreach (string file in sourceFiles)
+              {
+                  logWriter.WriteLine("Processing file: {0}", file);
+                  Console.WriteLine("Processing file: {0}", file);
+				  string fullFileName = Path.Combine(grpcSrcFileDirectory, file);
+                  if (File.Exists(fullFileName))
+                  {
+                    rProcInfo.Arguments = " -I" + grpcSrcFileDirectory + " --csharp_out " + grpcOutputDirectory
+                        + " " + fullFileName + " --grpc_out " + grpcOutputDirectory
+                        + " --plugin=protoc-gen-grpc=" + grpcPluginName;
+                    logWriter.WriteLine("Command: {0}", rProcInfo.Arguments);
+                    StringBuilder stdOutBuilder = new StringBuilder();
+                    StringBuilder stdErrBuilder = new StringBuilder();
+                    using (Process rProc = Process.Start(rProcInfo))
+                    {
+                      var stdOutTask = System.Threading.Tasks.Task.Run(
+                        () => stdOutBuilder.Append(rProc.StandardOutput.ReadToEnd()));
+                      var stdErrTask = System.Threading.Tasks.Task.Run(
+                        () => stdErrBuilder.Append(rProc.StandardError.ReadToEnd()));
+                      rProc.WaitForExit();
+                      conversionError = rProc.ExitCode != 0;
+                      // Wait for std out and error readers.
+                      stdOutTask.Wait();
+                      stdErrTask.Wait();
+                    }
+                    logWriter.WriteLine("[StdOut]:");
+                    logWriter.WriteLine(stdOutBuilder.ToString());
+                    logWriter.WriteLine("[StdErr]:");
+                    logWriter.WriteLine(stdErrBuilder.ToString());
+                  }
+              }
+          }
+          if (!conversionError)
+          {
+            Directory.Delete(tempDir, recursive : true);
+          }
+      ]]>
+      </Code>
+    </Task>
+  </UsingTask>
+</Project>
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Proto/Org.Apache.REEF.Bridge.Core.Proto.csproj b/lang/cs/Org.Apache.REEF.Bridge.Core.Proto/Org.Apache.REEF.Bridge.Core.Proto.csproj
new file mode 100644
index 0000000..e82394b
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Proto/Org.Apache.REEF.Bridge.Core.Proto.csproj
@@ -0,0 +1,85 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<Project>
+  <PropertyGroup>
+    <AssemblyName>Org.Apache.REEF.Bridge.Core.Proto</AssemblyName>
+    <Description>REEF Bridge Core Proto</Description>
+    <PackageTags>REEF Bridge Core Proto</PackageTags>
+    <TargetFramework>netstandard2.0</TargetFramework>
+	<ProtoVersion>3.6.0</ProtoVersion>
+	<GrpcVersion>1.13.0</GrpcVersion>
+  </PropertyGroup>
+
+  <Import Project="..\build.props" />
+  <ItemGroup>
+    <PackageReference Include="Google.Protobuf" Version="$(ProtoVersion)" />
+    <PackageReference Include="Grpc.Tools" Version="$(GrpcVersion)" />
+    <PackageReference Include="Grpc.Core" Version="$(GrpcVersion)">
+       <IncludeAssets>all</IncludeAssets>
+	     <ExcludeAssets>none</ExcludeAssets>
+	     <PrivateAssets>none</PrivateAssets>
+	  </PackageReference>
+  </ItemGroup>
+  <PropertyGroup>
+    <GrpcSchemaDirectory>$(REEF_Source_Folder)\lang\common\proto\bridge</GrpcSchemaDirectory>
+	<GrpcOutputDirectory>generated-sources</GrpcOutputDirectory>
+  </PropertyGroup>
+  <!-- Settings for Linux platforms -->
+  <PropertyGroup Condition="'$(OS)' != 'Windows_NT'">
+    <GrpcToolsDirectory>$(PackagesDir)\grpc.tools\$(GrpcVersion)\tools\linux_x64</GrpcToolsDirectory>
+  </PropertyGroup>
+  <!-- Settings for Windows platforms -->
+  <PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
+    <GrpcToolsDirectory>$(PackagesDir)\grpc.tools\$(GrpcVersion)\tools\windows_x64</GrpcToolsDirectory>
+    <GrpcToolsExtension>.exe</GrpcToolsExtension>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Grpc.Core">
+      <HintPath>$(GRrpcLibraryDirectory)\Grpc.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Google.Protobuf">
+      <HintPath>$(PackagesDir)\google.protobuf\$(ProtoVersion)\lib\netstandard1.0\Google.Protobuf.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+  </ItemGroup>
+
+  <Import Project="..\build.targets" />
+  
+  <PropertyGroup>  
+    <BuildDependsOn>  
+      CodeGeneration;  
+      $(BuildDependsOn)  
+    </BuildDependsOn>  
+  </PropertyGroup> 
+
+   <Import Project="$(ProjectDir)Grpc.targets" Condition="Exists('$(ProjectDir)Grpc.targets')" />
+  <Target Name="CodeGeneration">
+    <Message Text="Generating C# classes from gRPC proto files in $(GrpcSchemaDirectory) to $(ProjectDir)$(GrpcOutputDirectory) using tools directory $(GrpcToolsDirectory) with extension $(GrpcToolsExtension)" Importance="High" />
+    <GrpcToCSharp OutputDirectory="$(ProjectDir)$(GrpcOutputDirectory)" SourceFileList="DriverCommonProtocol.proto;ClientProtocol.proto;DriverClientProtocol.proto;DriverServiceProtocol.proto" GrpcSchemaDirectory="$(GrpcSchemaDirectory)" GrpcBinaryDirectory="$(GrpcToolsDirectory)" GrpcToolsExtension="$(GrpcToolsExtension)" /> 
+  </Target>
+  
+  <Target Name="UpdateCompileDependencies" AfterTargets="CodeGeneration" BeforeTargets="CoreCompile">
+    <Message Text="Update compile dependencies for gRPC proto files in $(ProjectDir)$(GrpcOutputDirectory)" Importance="High" /> 
+    <ItemGroup>
+      <Compile Include="$(ProjectDir)$(GrpcOutputDirectory)\**" />
+    </ItemGroup>
+  </Target>
+
+
+ </Project>
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/FailDriver.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/FailDriver.cs
new file mode 100644
index 0000000..3d14ae3
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/FailDriver.cs
@@ -0,0 +1,406 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using Org.Apache.REEF.Wake.Time;
+using Org.Apache.REEF.Wake.Time.Event;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Driver
+{
+    internal sealed class FailDriver :
+        IObserver<IAllocatedEvaluator>,
+        IObserver<ICompletedEvaluator>,
+        IObserver<IFailedEvaluator>,
+        IObserver<IRunningTask>,
+        IObserver<ICompletedTask>,
+        IObserver<IFailedTask>,
+        IObserver<ITaskMessage>,
+        IObserver<ISuspendedTask>,
+        IObserver<IFailedContext>,
+        IObserver<IClosedContext>,
+        IObserver<IContextMessage>,
+        IObserver<IActiveContext>,
+        IObserver<IDriverStarted>,
+        IObserver<IDriverStopped>,
+        IObserver<Alarm>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailDriver));
+
+        [NamedParameter("fail message type name")]
+        internal sealed class FailMsgTypeName : Name<string>
+        {
+        }
+
+        private enum DriverState
+        {
+            Init, SendMsg, Suspend, Resume, Close, Failed
+        }
+
+        private static readonly byte[] HelloStringByteArray = ByteUtilities.StringToByteArrays("MESSAGE::HELLO");
+
+        private static readonly int MsgDelay = 1000;
+
+        private static readonly ExpectedMessage[] EventSequence = new ExpectedMessage[]
+        {
+            new ExpectedMessage(typeof(FailDriver), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IDriverStarted), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IAllocatedEvaluator), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IFailedEvaluator), ExpectedMessage.RequiredFlag.Optional),
+            new ExpectedMessage(typeof(IActiveContext), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IContextMessage), ExpectedMessage.RequiredFlag.Optional),
+            new ExpectedMessage(typeof(IFailedContext), ExpectedMessage.RequiredFlag.Optional),
+            new ExpectedMessage(typeof(IRunningTask), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(Alarm), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(ITaskMessage), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(Alarm), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(ISuspendedTask), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IRunningTask), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(Alarm), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IFailedTask), ExpectedMessage.RequiredFlag.Optional),
+            new ExpectedMessage(typeof(ICompletedTask), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(ICompletedTask), ExpectedMessage.RequiredFlag.Optional),
+            new ExpectedMessage(typeof(ICompletedEvaluator), ExpectedMessage.RequiredFlag.Required),
+            new ExpectedMessage(typeof(IDriverStopped), ExpectedMessage.RequiredFlag.Required)
+        };
+
+        private static readonly Dictionary<string, Type> TypeHash = new Dictionary<string, Type>()
+        {
+            {typeof(NoopTask).FullName, typeof(NoopTask)},
+            {typeof(FailDriver).FullName, typeof(FailDriver)},
+            {typeof(IDriverStarted).FullName, typeof(IDriverStarted)},
+            {typeof(IAllocatedEvaluator).FullName, typeof(IAllocatedEvaluator)},
+            {typeof(IFailedEvaluator).FullName, typeof(IFailedEvaluator)},
+            {typeof(IActiveContext).FullName, typeof(IActiveContext)},
+            {typeof(IContextMessage).FullName, typeof(IContextMessage)},
+            {typeof(IFailedContext).FullName, typeof(IFailedContext)},
+            {typeof(IRunningTask).FullName, typeof(IRunningTask)},
+            {typeof(Alarm).FullName, typeof(Alarm)},
+            {typeof(ISuspendedTask).FullName, typeof(ISuspendedTask)},
+            {typeof(IFailedTask).FullName, typeof(IFailedTask)},
+            {typeof(ICompletedTask).FullName, typeof(ICompletedTask)},
+            {typeof(ITaskMessage).FullName, typeof(ITaskMessage)},
+            {typeof(ICompletedEvaluator).FullName, typeof(ICompletedEvaluator)},
+            {typeof(IDriverStopped).FullName, typeof(IDriverStopped)}
+        };
+
+        private readonly Type _failMsgClass;
+        private readonly IEvaluatorRequestor _requestor;
+        private readonly IClock _clock;
+        private IRunningTask _task = null;
+        private int _expectIdx = 0;
+        private DriverState _state = DriverState.Init;
+
+        [Inject]
+        public FailDriver([Parameter(Value = typeof(FailMsgTypeName))] string failMsgTypeName,
+            IEvaluatorRequestor requestor, IClock clock)
+        {
+            _clock = clock;
+            _requestor = requestor;
+            if (TypeHash.ContainsKey(failMsgTypeName))
+            {
+                _failMsgClass = TypeHash[failMsgTypeName];
+            }
+            else
+            {
+                _failMsgClass = typeof(FailDriver).Assembly.GetType(failMsgTypeName, true);
+            }
+            CheckMsgOrder(this);
+        }
+
+        public void OnError(System.Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        private void CheckMsgOrder(object obj)
+        {
+            string msgClassName = _failMsgClass.FullName;
+            Log.Log(Level.Info, "Driver state {0} event sequence {1} message obj type {2}",
+                _state, EventSequence[_expectIdx].Type, obj.GetType());
+
+            if (_state == DriverState.Failed)
+            {
+                // If already failed, do not do anything
+                return;
+            }
+
+            // Simulate failure at this step?
+            if (_failMsgClass.IsInstanceOfType(obj))
+            {
+                _state = DriverState.Failed;
+            }
+
+            // Make sure events arrive in the right order (specified in EVENT_SEQUENCE):
+            bool notFound = true;
+            for (; _expectIdx < EventSequence.Length; ++_expectIdx)
+            {
+                if (EventSequence[_expectIdx].Type.IsInstanceOfType(obj))
+                {
+                    Log.Log(Level.Info, "Object type {0} is instance of expected type {1}", new object[] { obj.GetType(), EventSequence[_expectIdx].Type });
+                    notFound = false;
+                    break;
+                }
+                else if (EventSequence[_expectIdx].Flag == ExpectedMessage.RequiredFlag.Required)
+                {
+                    Log.Log(Level.Info, "Object type {0} is NOT instance of expected type {1}", new object[] { obj.GetType(), EventSequence[_expectIdx].Type });
+                    break;
+                }
+            }
+
+            if (notFound)
+            {
+                Log.Log(Level.Info, "Event out of sequence: Driver state {0} event sequence {1} message obj type {2}",
+                    new object[] { _state, EventSequence[_expectIdx].Type, obj.GetType() });
+                throw new DriverSideFailure("Event out of sequence: " + msgClassName);
+            }
+
+            Log.Log(Level.Info, "{0}: send: {1} got: {2}", new object[] {
+                _state, EventSequence[_expectIdx], msgClassName});
+
+            ++_expectIdx;
+
+            if (_state == DriverState.Failed)
+            {
+                SimulatedDriverFailure ex = new SimulatedDriverFailure(
+                    "Simulated Failure at FailDriver :: " + msgClassName);
+                Log.Log(Level.Info, "Simulated Failure:", ex);
+                throw ex;
+            }
+        }
+
+        private sealed class ExpectedMessage
+        {
+            public enum RequiredFlag
+            {
+                Required,
+                Optional
+            }
+
+            public RequiredFlag Flag { get; }
+
+            public Type Type { get; }
+
+            public ExpectedMessage(Type type, RequiredFlag flag)
+            {
+                Type = type;
+                Flag = flag;
+            }
+        }
+
+        public void OnNext(IAllocatedEvaluator eval)
+        {
+            CheckMsgOrder(eval);
+            try
+            {
+                eval.SubmitContext(ContextConfiguration.ConfigurationModule
+                    .Set(ContextConfiguration.Identifier, "FailContext_" + eval.Id)
+                    .Build());
+            }
+            catch (BindException ex)
+            {
+                Log.Log(Level.Warning, "Context configuration error", ex);
+                throw new IllegalStateException("context configuration error", ex);
+            }
+        }
+
+        public void OnNext(ICompletedEvaluator eval)
+        {
+            CheckMsgOrder(eval);
+            // noop
+        }
+
+        public void OnNext(IFailedEvaluator eval)
+        {
+            Log.Log(Level.Warning, "Evaluator failed: " + eval.Id, eval.EvaluatorException);
+            CheckMsgOrder(eval);
+            throw new IllegalStateException("failed evaluator illegal state", eval.EvaluatorException);
+        }
+
+        public void OnNext(IActiveContext context)
+        {
+            CheckMsgOrder(context);
+            try
+            {
+                context.SubmitTask(TaskConfiguration.ConfigurationModule
+                    .Set(TaskConfiguration.Identifier, "FailTask_" + context.Id)
+                    .Set(TaskConfiguration.Task, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnMessage, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnSuspend, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnClose, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnTaskStop, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnSendMessage, GenericType<NoopTask>.Class)
+                    .Build());
+            }
+            catch (BindException ex)
+            {
+                Log.Log(Level.Warning, "Task configuration error", ex);
+                throw new IllegalStateException("task configuration error", ex);
+            }
+        }
+
+        public void OnNext(IContextMessage message)
+        {
+            CheckMsgOrder(message);
+            // noop
+        }
+
+        public void OnNext(IClosedContext context)
+        {
+            CheckMsgOrder(context);
+            // noop
+        }
+
+        public void OnNext(IFailedContext context)
+        {
+            Log.Log(Level.Warning, "Context failed: " + context.Id);
+            CheckMsgOrder(context);
+        }
+
+        public void OnNext(IRunningTask runningTask)
+        {
+            CheckMsgOrder(runningTask);
+            _task = runningTask;
+            switch (_state)
+            {
+                case DriverState.Init:
+                    Log.Log(Level.Info, "Move to state {0}", DriverState.SendMsg);
+                    _state = DriverState.SendMsg;
+                    break;
+
+                case DriverState.Resume:
+                    Log.Log(Level.Info, "Move to state {0}", DriverState.Close);
+                    _state = DriverState.Close;
+                    break;
+
+                default:
+                    Log.Log(Level.Warning, "Unexpected state at TaskRuntime: {0}", _state);
+                    throw new DriverSideFailure("Unexpected state: " + _state);
+            }
+
+            // After a delay, send message or suspend the task:
+            _clock.ScheduleAlarm(MsgDelay, this);
+        }
+
+        public void OnNext(ISuspendedTask suspendedTask)
+        {
+            CheckMsgOrder(suspendedTask);
+            _state = DriverState.Resume;
+            try
+            {
+                suspendedTask.ActiveContext.SubmitTask(TaskConfiguration.ConfigurationModule
+                    .Set(TaskConfiguration.Identifier, suspendedTask.Id + "_RESUMED")
+                    .Set(TaskConfiguration.Task, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnMessage, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnSuspend, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnClose, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnTaskStop, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.OnSendMessage, GenericType<NoopTask>.Class)
+                    .Set(TaskConfiguration.Memento, ByteUtilities.ByteArraysToString(HelloStringByteArray))
+                    .Build());
+            }
+            catch (BindException ex)
+            {
+                Log.Log(Level.Error, "Task configuration error", ex);
+                throw new DriverSideFailure("Task configuration error", ex);
+            }
+        }
+
+        public void OnNext(ITaskMessage msg)
+        {
+            CheckMsgOrder(msg);
+            Debug.Assert(Enumerable.SequenceEqual(HelloStringByteArray, msg.Message));
+            Debug.Assert(_state == DriverState.SendMsg);
+            _state = DriverState.Suspend;
+            _clock.ScheduleAlarm(MsgDelay, this);
+        }
+
+        public void OnNext(IFailedTask failedTask)
+        {
+            Log.Log(Level.Warning, "Task failed: " + failedTask.Id, failedTask.Reason.OrElse(null));
+            CheckMsgOrder(failedTask);
+            if (failedTask.GetActiveContext().IsPresent())
+            {
+                failedTask.GetActiveContext().Value.Dispose();
+            }
+        }
+
+        public void OnNext(ICompletedTask completedTask)
+        {
+            CheckMsgOrder(completedTask);
+            completedTask.ActiveContext.Dispose();
+        }
+
+        public void OnNext(IDriverStarted time)
+        {
+            CheckMsgOrder(time);
+            _requestor.Submit(_requestor.NewBuilder()
+                .SetNumber(1).SetMegabytes(128).SetCores(1).Build());
+        }
+
+        public void OnNext(Alarm time)
+        {
+            CheckMsgOrder(time);
+            switch (_state)
+            {
+                case DriverState.SendMsg:
+                    Log.Log(Level.Info, "Send message to task {0}", _task.Id);
+                    _task.Send(HelloStringByteArray);
+                    break;
+
+                case DriverState.Suspend:
+                    Log.Log(Level.Info, "Suspend task {0}", _task.Id);
+                    _task.Suspend();
+                    break;
+
+                case DriverState.Close:
+                    Log.Log(Level.Info, "Close task {0}", _task.Id);
+                    _task.Dispose();
+                    break;
+
+                default:
+                    Log.Log(Level.Warning, "Unexpected state at AlarmHandler: {0}", _state);
+                    throw new DriverSideFailure("Unexpected state: " + _state);
+            }
+        }
+
+        public void OnNext(IDriverStopped time)
+        {
+            CheckMsgOrder(time);
+            // noop
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/FailDriverClient.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/FailDriverClient.cs
new file mode 100644
index 0000000..99b54e3
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/FailDriverClient.cs
@@ -0,0 +1,94 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config;
+using Org.Apache.REEF.Bridge.Core.Grpc.Client;
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+using System;
+using System.Threading;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Driver
+{
+    public sealed class FailDriverClient
+    {
+        private static IConfiguration BuildAppDriverConfig(Type failMsgClass)
+        {
+            IConfiguration driverConfig = DriverApplicationConfiguration.ConfigurationModule
+                .Set(DriverApplicationConfiguration.OnDriverStarted, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnDriverStopped, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorAllocated, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorCompleted, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorFailed, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnContextActive, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnContextMessage, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnContextClosed, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnContextFailed, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskRunning, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskSuspended, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskMessage, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskFailed, GenericType<FailDriver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskCompleted, GenericType<FailDriver>.Class)
+                .Build();
+
+            return TangFactory.GetTang().NewConfigurationBuilder(driverConfig)
+                .BindNamedParameter(typeof(FailDriver.FailMsgTypeName), failMsgClass.FullName)
+                .Build();
+        }
+
+        /**
+         * Run REEF on specified runtime and fail (raise an exception) in a specified class.
+         * @param failMsgClass A class that should fail during the test.
+         * @param runtimeConfig REEF runtime configuration. Can be e.g. Local or YARN.
+         * @param timeOut REEF application timeout.
+         * @return launcher status - usually FAIL.
+         * @throws InjectionException configuration error.
+         */
+
+        public static LauncherStatus RunClient(Type failMsgClass, IConfiguration runtimeConfig, TimeSpan timeout)
+        {
+            // The JobSubmission contains the Driver configuration as well as the files needed on the Driver.
+            var driverRuntimeConfiguration = DriverRuntimeConfiguration.ConfigurationModule
+                .Set(DriverRuntimeConfiguration.OsType, GenericType<OsWindows>.Class)
+                .Set(DriverRuntimeConfiguration.JobId, "Fail_" + failMsgClass.Name);
+            driverRuntimeConfiguration = DriverRuntimeConfiguration
+                .AddGlobalAssemblyForType(driverRuntimeConfiguration, typeof(FailDriver));
+
+            var source = new CancellationTokenSource();
+            source.CancelAfter(timeout);
+            using (var launcher = ClientLauncherFactory.GetLauncher(runtimeConfig, driverRuntimeConfiguration.Build()))
+            {
+                var task = launcher.SubmitAsync(BuildAppDriverConfig(failMsgClass), source.Token);
+                try
+                {
+                    return task.Result;
+                }
+                catch (Exception)
+                {
+                    if (task.IsCanceled)
+                    {
+                        throw new TimeoutException($"Job timed out after {timeout}");
+                    }
+
+                    throw;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/NoopTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/NoopTask.cs
new file mode 100644
index 0000000..1e5fd48
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Driver/NoopTask.cs
@@ -0,0 +1,151 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Common.Tasks.Events;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Threading;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Driver
+{
+    internal sealed class NoopTask :
+        ITask,
+        ITaskMessageSource,
+        IDriverMessageHandler,
+        IObserver<ISuspendEvent>,
+        IObserver<ITaskStop>,
+        IObserver<ICloseEvent>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(NoopTask));
+
+        private static readonly TaskMessage InitMessage =
+            TaskMessage.From("nooptask", ByteUtilities.StringToByteArrays("MESSAGE::INIT"));
+
+        private bool _isRunning = true;
+        private Optional<TaskMessage> _message = Utilities.Optional<TaskMessage>.Empty();
+
+        [Inject]
+        private NoopTask()
+        {
+            Log.Log(Level.Info, "NoopTask created.");
+        }
+
+        public byte[] Call(byte[] memento)
+        {
+            _isRunning = true;
+            while (_isRunning)
+            {
+                try
+                {
+                    Log.Log(Level.Info, "NoopTask.call(): Waiting for the message.");
+                    lock (this)
+                    {
+                        Monitor.Wait(this);
+                    }
+                }
+                catch (System.Threading.ThreadInterruptedException ex)
+                {
+                    Log.Log(Level.Warning, "NoopTask.wait() interrupted.", ex);
+                }
+            }
+
+            Log.Log(Level.Info,
+                "NoopTask.call(): Exiting with message {0}",
+                ByteUtilities.ByteArraysToString(_message.OrElse(InitMessage).Message));
+            return _message.OrElse(InitMessage).Message;
+        }
+
+        public Optional<TaskMessage> Message
+        {
+            get
+            {
+                Log.Log(Level.Info,
+                    "NoopTask.getMessage() invoked: {0}",
+                    ByteUtilities.ByteArraysToString(_message.OrElse(InitMessage).Message));
+                return _message;
+            }
+        }
+
+        public void Dispose()
+        {
+            Log.Log(Level.Info, "NoopTask.stopTask() invoked.");
+            _isRunning = false;
+            lock (this)
+            {
+                Monitor.Pulse(this);
+            }
+        }
+
+        public void OnError(System.Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// Handler for SuspendEvent.
+        /// </summary>
+        /// <param name="suspendEvent"></param>
+        public void OnNext(ISuspendEvent suspendEvent)
+        {
+            Log.Log(Level.Info, "NoopTask.TaskSuspendHandler.OnNext() invoked.");
+            Dispose();
+        }
+
+        /// <summary>
+        /// Handler for TaskStop.
+        /// </summary>
+        /// <param name="value"></param>
+        public void OnNext(ITaskStop value)
+        {
+            Log.Log(Level.Info, "NoopTask.TaskStopHandler.OnNext() invoked.");
+        }
+
+        /// <summary>
+        /// Handler for CloseEvent.
+        /// </summary>
+        /// <param name="closeEvent"></param>
+        public void OnNext(ICloseEvent closeEvent)
+        {
+            Log.Log(Level.Info, "NoopTask.TaskCloseHandler.OnNext() invoked.");
+            Dispose();
+        }
+
+        /// <summary>
+        /// Handler for DriverMessage.
+        /// </summary>
+        /// <param name="driverMessage"></param>
+        public void Handle(IDriverMessage driverMessage)
+        {
+            byte[] msg = driverMessage.Message.Value;
+            Log.Log(Level.Info,
+                "NoopTask.DriverMessageHandler.Handle() invoked: {0}",
+                ByteUtilities.ByteArraysToString(msg));
+            lock (this)
+            {
+                _message = Utilities.Optional<TaskMessage>.Of(TaskMessage.From("nooptask", msg));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/DriverSideFailure.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/DriverSideFailure.cs
new file mode 100644
index 0000000..2681b27
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/DriverSideFailure.cs
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException
+{
+    [Serializable]
+    public sealed class DriverSideFailure : System.Exception
+    {
+        public DriverSideFailure(string message) : base(message)
+        {
+        }
+
+        public DriverSideFailure(string message, System.Exception innerException) : base(message, innerException)
+        {
+        }
+
+        protected DriverSideFailure(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/SimulatedDriverFailure.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/SimulatedDriverFailure.cs
new file mode 100644
index 0000000..cdf0fc0
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/SimulatedDriverFailure.cs
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException
+{
+    [Serializable]
+    public sealed class SimulatedDriverFailure : System.Exception
+    {
+        public SimulatedDriverFailure(string message) : base(message)
+        {
+        }
+
+        public SimulatedDriverFailure(string message, System.Exception innerException) : base(message, innerException)
+        {
+        }
+
+        protected SimulatedDriverFailure(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/SimulatedTaskFailure.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/SimulatedTaskFailure.cs
new file mode 100644
index 0000000..e1c0495
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Exception/SimulatedTaskFailure.cs
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// // or more contributor license agreements.  See the NOTICE file
+// // distributed with this work for additional information
+// // regarding copyright ownership.  The ASF licenses this file
+// // to you under the Apache License, Version 2.0 (the
+// // "License"); you may not use this file except in compliance
+// // with the License.  You may obtain a copy of the License at
+// //
+// //   http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing,
+// // software distributed under the License is distributed on an
+// // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// // KIND, either express or implied.  See the License for the
+// // specific language governing permissions and limitations
+// // under the License.
+using System;
+using System.Runtime.Serialization;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException
+{
+    [Serializable]
+    internal sealed class SimulatedTaskFailure : System.Exception
+    {
+        public SimulatedTaskFailure(string message) : base(message)
+        {
+        }
+
+        public SimulatedTaskFailure(string message, System.Exception innerException) : base(message, innerException)
+        {
+        }
+
+        protected SimulatedTaskFailure(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/BlockingCallTaskBase.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/BlockingCallTaskBase.cs
new file mode 100644
index 0000000..bc2b350
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/BlockingCallTaskBase.cs
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using System.Threading;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal abstract class BlockingCallTaskBase : ITask
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(BlockingCallTaskBase));
+
+        private bool _isRunning = true;
+
+        public void Dispose()
+        {
+            lock (this)
+            {
+                _isRunning = false;
+                Monitor.Pulse(this);
+            }
+        }
+
+        public byte[] Call(byte[] memento)
+        {
+            lock (this)
+            {
+                Log.Log(Level.Info, "BlockingCallTaskBase.call() invoked. Waiting for the message.");
+                while (_isRunning)
+                {
+                    try
+                    {
+                        Monitor.Wait(this);
+                    }
+                    catch (System.Exception ex)
+                    {
+                        Log.Log(Level.Warning, "wait() interrupted.", ex);
+                    }
+                }
+            }
+            return new byte[0];
+        }
+
+        public void OnError(System.Exception error)
+        {
+            Log.Log(Level.Error, "OnError called", error);
+            throw error;
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotSupportedException("OnComplete not supported by task");
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/Driver.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/Driver.cs
new file mode 100644
index 0000000..4ace9a1
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/Driver.cs
@@ -0,0 +1,185 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using Org.Apache.REEF.Tang.Formats;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class Driver :
+        IObserver<IAllocatedEvaluator>,
+        IObserver<IRunningTask>,
+        IObserver<IActiveContext>,
+        IObserver<IDriverStarted>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(Driver));
+
+        [NamedParameter("the fail task to test")]
+        internal sealed class FailTaskName : Name<string>
+        {
+        }
+
+        private readonly string _failTaskName;
+
+        private readonly IEvaluatorRequestor _evaluatorRequestor;
+
+        private string _taskId;
+
+        [Inject]
+        private Driver(IEvaluatorRequestor evaluatorRequestor,
+            [Parameter(Value = typeof(FailTaskName))]
+            string failTaskName)
+        {
+            _failTaskName = failTaskName;
+            _evaluatorRequestor = evaluatorRequestor;
+        }
+
+        public void OnError(System.Exception error)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnCompleted()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void OnNext(IAllocatedEvaluator eval)
+        {
+            try
+            {
+                _taskId = _failTaskName + "_" + eval.Id;
+                Log.Log(Level.Info, "Submit task: {0}", _taskId);
+
+                IConfiguration contextConfig =
+                    ContextConfiguration.ConfigurationModule.Set(ContextConfiguration.Identifier, _taskId).Build();
+
+                ConfigurationModule taskConfig =
+                    TaskConfiguration.ConfigurationModule.Set(TaskConfiguration.Identifier, _taskId);
+
+                switch (_failTaskName)
+                {
+                    case "FailTask":
+                        taskConfig = taskConfig.Set(TaskConfiguration.Task, GenericType<FailTask>.Class);
+                        break;
+
+                    case "FailTaskCall":
+                        taskConfig = taskConfig.Set(TaskConfiguration.Task, GenericType<FailTaskCall>.Class);
+                        break;
+
+                    case "FailTaskMsg":
+                        taskConfig = taskConfig
+                            .Set(TaskConfiguration.Task, GenericType<FailTaskMsg>.Class)
+                            .Set(TaskConfiguration.OnMessage, GenericType<FailTaskMsg>.Class);
+                        break;
+
+                    case "FailTaskSuspend":
+                        taskConfig = taskConfig
+                            .Set(TaskConfiguration.Task, GenericType<FailTaskSuspend>.Class)
+                            .Set(TaskConfiguration.OnSuspend, GenericType<FailTaskSuspend>.Class);
+                        break;
+
+                    case "FailTaskStart":
+                        taskConfig = taskConfig
+                            .Set(TaskConfiguration.Task, GenericType<FailTaskStart>.Class)
+                            .Set(TaskConfiguration.OnTaskStart, GenericType<FailTaskStart>.Class);
+                        break;
+
+                    case "FailTaskStop":
+                        taskConfig = taskConfig
+                            .Set(TaskConfiguration.Task, GenericType<FailTaskStop>.Class)
+                            .Set(TaskConfiguration.OnTaskStop, GenericType<FailTaskStop>.Class)
+                            .Set(TaskConfiguration.OnClose, GenericType<FailTaskStop>.Class);
+                        break;
+
+                    case "FailTaskClose":
+                        taskConfig = taskConfig
+                            .Set(TaskConfiguration.Task, GenericType<FailTaskClose>.Class)
+                            .Set(TaskConfiguration.OnClose, GenericType<FailTaskClose>.Class);
+                        break;
+
+                    default:
+                        break;
+                }
+
+                eval.SubmitContextAndTask(contextConfig, taskConfig.Build());
+            }
+            catch (BindException ex)
+            {
+                Log.Log(Level.Warning, "Configuration error", ex);
+                throw new DriverSideFailure("Configuration error", ex);
+            }
+        }
+
+        public void OnNext(IRunningTask task)
+        {
+            Log.Log(Level.Info,
+                "TaskRuntime: {0} expect {1}",
+                task.Id, _taskId);
+
+            if (!_taskId.Equals(task.Id))
+            {
+                throw new DriverSideFailure($"Task ID {task.Id} not equal expected ID {_taskId}");
+            }
+
+            switch (_failTaskName)
+            {
+                case "FailTaskMsg":
+                    Log.Log(Level.Info, "TaskRuntime: Send message: {0}", task);
+                    task.Send(new byte[0]);
+                    break;
+
+                case "FailTaskSuspend":
+                    Log.Log(Level.Info, "TaskRuntime: Suspend: {0}", task);
+                    task.Suspend();
+                    break;
+
+                case "FailTaskStop":
+                case "FailTaskClose":
+                    Log.Log(Level.Info, "TaskRuntime: Stop/Close: {0}", task);
+                    task.Dispose();
+                    break;
+
+                default:
+                    break;
+            }
+        }
+
+        public void OnNext(IActiveContext context)
+        {
+            throw new DriverSideFailure($"Unexpected ActiveContext message: {context.Id}");
+        }
+
+        public void OnNext(IDriverStarted start)
+        {
+            Log.Log(Level.Info, "StartTime: {0}", start);
+            _evaluatorRequestor.Submit(_evaluatorRequestor.NewBuilder()
+                .SetNumber(1).SetMegabytes(128).SetNumber(1).Build());
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTask.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTask.cs
new file mode 100644
index 0000000..6f8f296
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTask.cs
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Exceptions;
+using Org.Apache.REEF.Utilities.Logging;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal class FailTask : ITask
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTask));
+
+        [Inject]
+        private FailTask()
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTask constructor called.");
+            Log.Log(Level.Info, "FailTask created - failing now: {0}", ex);
+            throw ex;
+        }
+
+        public void Dispose()
+        {
+        }
+
+        public byte[] Call(byte[] memento)
+        {
+            throw new IllegalStateException("should not make it to this point");
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskCall.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskCall.cs
new file mode 100644
index 0000000..b4f37e9
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskCall.cs
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class FailTaskCall : ITask
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTaskCall));
+
+        [Inject]
+        private FailTaskCall()
+        {
+            Log.Log(Level.Info, "task created");
+        }
+
+        public void Dispose()
+        {
+        }
+
+        public byte[] Call(byte[] memento)
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTaskCall.call() invoked.");
+            Log.Log(Level.Info, "FailTaskCall.call() invoked: {0}", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskClient.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskClient.cs
new file mode 100644
index 0000000..5bd5c89
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskClient.cs
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config;
+using Org.Apache.REEF.Bridge.Core.Grpc.Client;
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+using System;
+using System.Threading;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal static class FailTaskClient
+    {
+        private static IConfiguration BuildAppDriverConfig(Type failTaskName)
+        {
+            IConfiguration driverConfig = DriverApplicationConfiguration.ConfigurationModule
+                .Set(DriverApplicationConfiguration.OnDriverStarted, GenericType<Driver>.Class)
+                .Set(DriverApplicationConfiguration.OnEvaluatorAllocated, GenericType<Driver>.Class)
+                .Set(DriverApplicationConfiguration.OnContextActive, GenericType<Driver>.Class)
+                .Set(DriverApplicationConfiguration.OnTaskRunning, GenericType<Driver>.Class)
+                .Build();
+
+            return TangFactory.GetTang().NewConfigurationBuilder(driverConfig)
+                .BindNamedParameter(typeof(Driver.FailTaskName), failTaskName.Name)
+                .Build();
+        }
+
+        /**
+         * Run REEF on specified runtime and fail (raise an exception) in a specified class.
+         * @param failTaskType A class that should fail during the test.
+         * @param runtimeConfig REEF runtime configuration. Can be e.g. Local or YARN.
+         * @param timeOut REEF application timeout.
+         * @return launcher status - usually FAIL.
+         * @throws InjectionException configuration error.
+         */
+
+        public static LauncherStatus Run(Type failTaskType, IConfiguration runtimeConfig, TimeSpan timeout)
+        {
+            var driverRuntimeConfiguration = DriverRuntimeConfiguration.ConfigurationModule
+                .Set(DriverRuntimeConfiguration.OsType, GenericType<OsWindows>.Class)
+                .Set(DriverRuntimeConfiguration.JobId, "Fail_" + failTaskType.Name);
+            driverRuntimeConfiguration = DriverRuntimeConfiguration
+                .AddGlobalAssemblyForType(driverRuntimeConfiguration, typeof(Driver));
+
+            var source = new CancellationTokenSource();
+            source.CancelAfter(timeout);
+            using (var launcher = ClientLauncherFactory.GetLauncher(runtimeConfig, driverRuntimeConfiguration.Build()))
+            {
+                var task = launcher.SubmitAsync(BuildAppDriverConfig(failTaskType), source.Token);
+                try
+                {
+                    return task.Result;
+                }
+                catch (Exception)
+                {
+                    if (task.IsCanceled)
+                    {
+                        throw new TimeoutException($"Job timed out after {timeout}");
+                    }
+
+                    throw;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskClose.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskClose.cs
new file mode 100644
index 0000000..caf7290
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskClose.cs
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks.Events;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class FailTaskClose : BlockingCallTaskBase, IObserver<ICloseEvent>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTaskClose));
+
+        [Inject]
+        private FailTaskClose()
+        {
+            Log.Log(Level.Info, "task created");
+        }
+
+        public void OnNext(ICloseEvent value)
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTaskClose.send() invoked.");
+            Log.Log(Level.Info, "FailTaskClose.onNext() invoked. Raise exception: {0}", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskMsg.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskMsg.cs
new file mode 100644
index 0000000..1a9ab47
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskMsg.cs
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Common.Tasks.Events;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class FailTaskMsg : BlockingCallTaskBase, IDriverMessageHandler
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTaskMsg));
+
+        [Inject]
+        private FailTaskMsg()
+        {
+            Log.Log(Level.Info, "task created");
+        }
+
+        public void Handle(IDriverMessage message)
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTaskMsg.send() invoked.");
+            Log.Log(Level.Info, "FailTaskMsg.send() invoked: {0}", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskStart.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskStart.cs
new file mode 100644
index 0000000..f62195a
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskStart.cs
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks.Events;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class FailTaskStart : BlockingCallTaskBase, IObserver<ITaskStart>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTaskStart));
+
+        [Inject]
+        private FailTaskStart()
+        {
+            Log.Log(Level.Info, "task created");
+        }
+
+        public void OnNext(ITaskStart value)
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTaskMsg.send() invoked.");
+            Log.Log(Level.Info, "FailTaskMsg.send() invoked: {0}", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskStop.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskStop.cs
new file mode 100644
index 0000000..4571af3
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskStop.cs
@@ -0,0 +1,47 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks.Events;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class FailTaskStop : BlockingCallTaskBase, IObserver<ITaskStop>, IObserver<ICloseEvent>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTaskStop));
+
+        [Inject]
+        private FailTaskStop()
+        {
+            Log.Log(Level.Info, "task created");
+        }
+
+        public void OnNext(ICloseEvent value)
+        {
+            Dispose();
+        }
+
+        public void OnNext(ITaskStop value)
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTaskStop Failure.");
+            Log.Log(Level.Info, "FailTaskStop.onNext() invoked. Raise exception: {0}", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskSuspend.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskSuspend.cs
new file mode 100644
index 0000000..e11dbd0
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Task/FailTaskSuspend.cs
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Tasks.Events;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Task
+{
+    internal sealed class FailTaskSuspend : BlockingCallTaskBase, IObserver<ISuspendEvent>
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(FailTaskSuspend));
+
+        [Inject]
+        private FailTaskSuspend()
+        {
+            Log.Log(Level.Info, "task created");
+        }
+
+        public void OnNext(ISuspendEvent value)
+        {
+            SimulatedTaskFailure ex = new SimulatedTaskFailure("FailTaskSuspend.send() invoked.");
+            Log.Log(Level.Info, "FailTaskSuspend.send() invoked: {0}", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/FailDriverTest.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/FailDriverTest.cs
new file mode 100644
index 0000000..96ee0db
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/FailDriverTest.cs
@@ -0,0 +1,116 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime;
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.Driver;
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Wake.Time.Event;
+using System;
+using Xunit;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Test
+{
+    public sealed class FailDriverTest
+    {
+        private static readonly TimeSpan JobTimeout = TimeSpan.FromMinutes(5);
+
+        private static void FailOn(Type type)
+        {
+            var launchStatus = FailDriverClient.RunClient(type, LocalRuntimeConfiguration.ConfigurationModule.Build(), JobTimeout);
+            TestUtils.AssertLauncherFailure(launchStatus, typeof(SimulatedDriverFailure));
+        }
+
+        [Fact]
+        public void TestFailDriverConstructor()
+        {
+            FailOn(typeof(FailDriver));
+        }
+
+        [Fact]
+        public void TestFailDriverStart()
+        {
+            FailOn(typeof(IDriverStarted));
+        }
+
+        [Fact]
+        public void TestFailDriverAllocatedEvaluator()
+        {
+            FailOn(typeof(IAllocatedEvaluator));
+        }
+
+        [Fact]
+        public void TestFailDriverActiveContext()
+        {
+            FailOn(typeof(IActiveContext));
+        }
+
+        [Fact]
+        public void TestFailDriverRunningTask()
+        {
+            FailOn(typeof(IRunningTask));
+        }
+
+        [Fact]
+        public void TestFailDriverTaskMessage()
+        {
+            FailOn(typeof(ITaskMessage));
+        }
+
+        [Fact]
+        public void TestFailDriverSuspendedTask()
+        {
+            FailOn(typeof(ISuspendedTask));
+        }
+
+        [Fact]
+        public void TestFailDriverCompletedTask()
+        {
+            FailOn(typeof(ICompletedTask));
+        }
+
+        [Fact]
+        public void TestFailDriverCompletedEvaluator()
+        {
+            FailOn(typeof(ICompletedEvaluator));
+        }
+
+        [Fact]
+        public void TestFailDriverAlarm()
+        {
+            FailOn(typeof(Alarm));
+        }
+
+        [Fact]
+        public void TestFailDriverStop()
+        {
+            FailOn(typeof(IDriverStopped));
+        }
+
+        [Fact]
+        public void TestDriverCompleted()
+        {
+            // NoopTask can be replaced with any other class never used in FailDriver
+            LauncherStatus status = FailDriverClient.RunClient(typeof(NoopTask),
+                LocalRuntimeConfiguration.ConfigurationModule.Build(), JobTimeout);
+            Assert.Equal(LauncherStatus.CompletedStatus, status);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/FailTaskTest.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/FailTaskTest.cs
new file mode 100644
index 0000000..127ad6b
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/FailTaskTest.cs
@@ -0,0 +1,77 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Bridge.Core.Common.Client.Config.Runtime;
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.Task;
+using Org.Apache.REEF.Bridge.Core.Tests.Fail.ThreadInterruptedException;
+using System;
+using Xunit;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Test
+{
+    public sealed class FailTaskTest
+    {
+        private static readonly TimeSpan JobTimeout = TimeSpan.FromMinutes(5);
+
+        private static void FailOn(Type type)
+        {
+            var launchStatus = FailTaskClient.Run(type, LocalRuntimeConfiguration.ConfigurationModule.Build(), JobTimeout);
+            TestUtils.AssertLauncherFailure(launchStatus, typeof(SimulatedTaskFailure));
+        }
+
+        [Fact]
+        public void TestFailTask()
+        {
+            FailOn(typeof(FailTask));
+        }
+
+        [Fact]
+        public void TestFailTaskCall()
+        {
+            FailOn(typeof(FailTaskCall));
+        }
+
+        [Fact]
+        public void TestFailTaskMsg()
+        {
+            FailOn(typeof(FailTaskMsg));
+        }
+
+        [Fact]
+        public void TestFailTaskSuspend()
+        {
+            FailOn(typeof(FailTaskSuspend));
+        }
+
+        [Fact]
+        public void TestFailTaskStart()
+        {
+            FailOn(typeof(FailTaskStart));
+        }
+
+        [Fact]
+        public void TestFailTaskStop()
+        {
+            FailOn(typeof(FailTaskStop));
+        }
+
+        [Fact]
+        public void TestFailTaskClose()
+        {
+            FailOn(typeof(FailTaskClose));
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/TestUtils.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/TestUtils.cs
new file mode 100644
index 0000000..ae41a7d
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Fail/Test/TestUtils.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Client;
+using Org.Apache.REEF.Utilities.Logging;
+using System;
+using Xunit;
+
+namespace Org.Apache.REEF.Bridge.Core.Tests.Fail.Test
+{
+    internal static class TestUtils
+    {
+        private static readonly Logger Log = Logger.GetLogger(typeof(TestUtils));
+
+        public static void AssertLauncherFailure(LauncherStatus status, Type expectedFailureType)
+        {
+            Assert.Equal(LauncherStatus.FailedStatus, status);
+            var ex = status.Error.OrElse(null);
+            Assert.True(HasCause(ex, expectedFailureType), "Unexpected error: " + ex);
+        }
+
+        private static bool HasCause(Exception ex, Type exceptionType)
+        {
+            for (var exception = ex; exception != null; exception = exception.InnerException)
+            {
+                Log.Log(Level.Info, "Exception type {0}", exception.GetType());
+                if (exceptionType.IsInstanceOfType(exception))
+                {
+                    return true;
+                }
+                Log.Log(Level.Info, "Not instance of {0}", exceptionType);
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Org.Apache.REEF.Bridge.Core.Tests.csproj b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Org.Apache.REEF.Bridge.Core.Tests.csproj
new file mode 100644
index 0000000..4f285a6
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Org.Apache.REEF.Bridge.Core.Tests.csproj
@@ -0,0 +1,33 @@
+<Project>
+  <!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+  <PropertyGroup>
+    <AssemblyName>Org.Apache.REEF.Bridge.Core.Tests</AssemblyName>
+  </PropertyGroup>
+  <Import Project="..\build.Test.props" />
+  <ItemGroup>
+    <PackageReference Include="System.Threading.Threadpool" Version="4.3.0" />
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Common\Org.Apache.REEF.Bridge.Core.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Grpc\Org.Apache.REEF.Bridge.Core.Grpc.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Driver\Org.Apache.REEF.Bridge.Core.Driver.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Bridge.Core.Proto\Org.Apache.REEF.Bridge.Core.Proto.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Evaluator\Org.Apache.REEF.Evaluator.csproj" />
+    <ProjectReference Include="..\Org.Apache.REEF.Tang\Org.Apache.REEF.Tang.csproj" />
+  </ItemGroup>
+  <Import Project="..\build.Test.targets" />
+</Project>
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Properties/AssemblyInfo.cs b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..881078a
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Bridge.Core.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Xunit;
+
+[assembly: CollectionBehavior(DisableTestParallelization = true)]
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Bridge.JAR/Org.Apache.REEF.Bridge.JAR.csproj b/lang/cs/Org.Apache.REEF.Bridge.JAR/Org.Apache.REEF.Bridge.JAR.csproj
index 1ac6e73..8a15baf 100644
--- a/lang/cs/Org.Apache.REEF.Bridge.JAR/Org.Apache.REEF.Bridge.JAR.csproj
+++ b/lang/cs/Org.Apache.REEF.Bridge.JAR/Org.Apache.REEF.Bridge.JAR.csproj
@@ -18,7 +18,7 @@
   <PropertyGroup>
     <AssemblyName>Org.Apache.REEF.Bridge.JAR</AssemblyName>
     <Description>Helper project that builds the Bridge JAR </Description>
-    <TargetFramework>net461</TargetFramework>
+    <TargetFramework>netstandard2.0</TargetFramework>
   </PropertyGroup>
   <Import Project="..\build.props" />
   <PropertyGroup>
@@ -58,11 +58,15 @@
       <!--The shaded jar of the bridge (client side) -->
       <Client_JAR_Name>reef-bridge-client-$(REEF_Version)-shaded.jar</Client_JAR_Name>
       <Client_JAR>$(REEF_Source_Folder)\lang\java\reef-bridge-client\target\$(Client_JAR_Name)</Client_JAR>
+	  <!--The shaded jar of the bridge core -->
+      <BridgeCore_JAR_Name>reef-bridge-proto-java-$(REEF_Version)-jar-with-dependencies.jar</BridgeCore_JAR_Name>
+      <BridgeCore_JAR>$(REEF_Source_Folder)\lang\java\reef-bridge-proto-java\target\$(BridgeCore_JAR_Name)</BridgeCore_JAR>
     </PropertyGroup>
-    <Exec Command="call &quot;$(M2_HOME)\bin\mvn.cmd&quot; --projects lang/java/reef-bridge-java,lang/java/reef-bridge-client --also-make -TC1 -DskipTests -P!code-quality install" Condition="!Exists('$(Bridge_JAR)')" WorkingDirectory="$(REEF_Source_Folder)" />
+    <Exec Command="call &quot;$(M2_HOME)\bin\mvn.cmd&quot; --projects lang/java/reef-bridge-java,lang/java/reef-bridge-client,lang/java/reef-bridge-proto-java --also-make -TC1 -DskipTests -P!code-quality install" Condition="!Exists('$(Bridge_JAR)') Or !Exists('$(BridgeCore_JAR)')" WorkingDirectory="$(REEF_Source_Folder)" />
     <Message Text="Copying jar files to $(OutputPath)" Importance="high" />
     <Copy DestinationFolder="$(OutputPath)" SourceFiles="$(Bridge_JAR)" />
     <Copy DestinationFolder="$(OutputPath)" SourceFiles="$(Client_JAR)" />
+	<Copy DestinationFolder="$(OutputPath)" SourceFiles="$(BridgeCore_JAR)" />
   </Target>
   <!--
     Executes 'mvn clean', if the JAR exists.
@@ -75,10 +79,14 @@
       <!--The shaded jar of the bridge (client side) -->
       <Client_JAR_Name>reef-bridge-client-$(REEF_Version)-shaded.jar</Client_JAR_Name>
       <Client_JAR>$(REEF_Source_Folder)\lang\java\reef-bridge-client\target\$(Client_JAR_Name)</Client_JAR>
+	  <!--The shaded jar of the bridge core -->
+      <BridgeCore_JAR_Name>reef-bridge-proto-java-$(REEF_Version)-jar-with-dependencies.jar</BridgeCore_JAR_Name>
+      <BridgeCore_JAR>$(REEF_Source_Folder)\lang\java\reef-bridge-proto-java\target\$(Client_JAR_Name)</BridgeCore_JAR>
     </PropertyGroup>
-    <Exec Command="call &quot;$(M2_HOME)\bin\mvn.cmd&quot; -TC1 -DskipTests -q clean" Condition="Exists('$(Bridge_JAR)')" WorkingDirectory="$(REEF_Source_Folder)" />
+    <Exec Command="call &quot;$(M2_HOME)\bin\mvn.cmd&quot; -TC1 -DskipTests -q clean" Condition="Exists('$(Bridge_JAR)') Or Exists('$(BridgeCore_JAR)')" WorkingDirectory="$(REEF_Source_Folder)" />
     <Delete Files="$(OutputPath)\$(Bridge_JAR_Name)" />
     <Delete Files="$(OutputPath)\$(Client_JAR_Name)" />
+	    <Delete Files="$(OutputPath)\$(BridgeCore_JAR_Name)" />
   </Target>
   <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
   <Target Name="CheckPrerequisites" DependsOnTargets="Build" />
diff --git a/lang/cs/Org.Apache.REEF.Client/API/JobParameters.cs b/lang/cs/Org.Apache.REEF.Client/API/JobParameters.cs
index 5279e3a..215dfeb 100644
--- a/lang/cs/Org.Apache.REEF.Client/API/JobParameters.cs
+++ b/lang/cs/Org.Apache.REEF.Client/API/JobParameters.cs
@@ -32,6 +32,7 @@
         private readonly string _jobIdentifier;
         private readonly int _maxApplicationSubmissions;
         private readonly int _driverMemory;
+        private readonly int _driverCpuCores;
         private IDictionary<string, string> _jobSubmissionEnvMap;
         private readonly Optional<string> _stdoutFilePath;
         private readonly Optional<string> _stderrFilePath;
@@ -41,6 +42,7 @@
             string jobIdentifier, 
             int maxApplicationSubmissions, 
             int driverMemory,
+            int driverCpuCores,
             IDictionary<string, string> jobSubmissionEnvMap, 
             string stdoutFilePath,
             string stderrFilePath,
@@ -49,6 +51,7 @@
             _jobIdentifier = jobIdentifier;
             _maxApplicationSubmissions = maxApplicationSubmissions;
             _driverMemory = driverMemory;
+            _driverCpuCores = driverCpuCores;
             _jobSubmissionEnvMap = jobSubmissionEnvMap;
 
             _stdoutFilePath = string.IsNullOrWhiteSpace(stdoutFilePath) ? 
@@ -86,6 +89,14 @@
         }
 
         /// <summary>
+        /// The number of driver CPU cores.
+        /// </summary>
+        public int DriverCpuCores
+        {
+            get { return _driverCpuCores;  }
+        }
+
+        /// <summary>
         /// The job submission environment variable map.
         /// </summary>
         public IDictionary<string, string> JobSubmissionEnvMap
diff --git a/lang/cs/Org.Apache.REEF.Client/API/JobParametersBuilder.cs b/lang/cs/Org.Apache.REEF.Client/API/JobParametersBuilder.cs
index 39df14e..6b495fc 100644
--- a/lang/cs/Org.Apache.REEF.Client/API/JobParametersBuilder.cs
+++ b/lang/cs/Org.Apache.REEF.Client/API/JobParametersBuilder.cs
@@ -27,6 +27,7 @@
     {
         private string _jobIdentifier;
         private int _maxApplicationSubmissions = 1;
+        private int _driverCpuCores = 1;
         private int _driverMemory = 512;
         private string _stdoutFilePath = null;
         private string _stderrFilePath = null;
@@ -55,6 +56,7 @@
                 _jobIdentifier, 
                 _maxApplicationSubmissions, 
                 _driverMemory,
+                _driverCpuCores,
                 _jobSubmissionMap,
                 _stdoutFilePath,
                 _stderrFilePath,
@@ -92,6 +94,17 @@
         }
 
         /// <summary>
+        /// The number of cores to allocated for the driver
+        /// </summary>
+        /// <param name="driverCpuCores">number of cores</param>
+        /// <returns></returns>
+        public JobParametersBuilder SetDriverCpuCores(int driverCpuCores)
+        {
+            _driverCpuCores = driverCpuCores;
+            return this;
+        }
+
+        /// <summary>
         /// Set job submission environment variable.
         /// If the variable is already in the map, override it. 
         /// </summary>
diff --git a/lang/cs/Org.Apache.REEF.Client/Common/JavaClientLauncher.cs b/lang/cs/Org.Apache.REEF.Client/Common/JavaClientLauncher.cs
index bc90c44..a571f2a 100644
--- a/lang/cs/Org.Apache.REEF.Client/Common/JavaClientLauncher.cs
+++ b/lang/cs/Org.Apache.REEF.Client/Common/JavaClientLauncher.cs
@@ -154,8 +154,15 @@
             var javaPath = Path.Combine(javaBinPath, "java.exe");
             if (!File.Exists(javaPath))
             {
-                throw new JavaNotFoundException(
-                    "Could not find java.exe on this machine. Is Java installed and JAVA_HOME set?", javaPath);
+                var linuxJavaPath = Path.Combine(javaBinPath, "java");
+                if (!File.Exists(linuxJavaPath))
+                {
+                    throw new JavaNotFoundException(
+                        "Could not find java executable on this machine. Is Java installed and JAVA_HOME set?",
+                        javaPath);
+                }
+
+                return linuxJavaPath;
             }
             return javaPath;
         }
diff --git a/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj b/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
index b94fccb..5ad2c2d 100644
--- a/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
+++ b/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
@@ -93,7 +93,7 @@
       var srcDir = @"lang\cs\Org.Apache.REEF.Client\Properties";
       var binDir = @"lang\cs\bin\.netcore";
       var resxInputPath  = Path.Combine(ProjectFolder, srcDir, "Resources.xml");      
-      var resourceDir = Path.Combine(ProjectFolder, binDir, DebugOrRelease, "Org.Apache.REEF.Bridge.JAR", "net461");
+      var resourceDir = Path.Combine(ProjectFolder, binDir, DebugOrRelease, "Org.Apache.REEF.Bridge.JAR", "netstandard2.0");
       var clrDriverDir = Path.Combine(ProjectFolder, binDir, DebugOrRelease, "Org.Apache.REEF.Bridge");
       var byteArrayType = ";System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
       var jarRest = reefVersion + "-shaded.jar" + byteArrayType;
@@ -154,7 +154,7 @@
     <Copy SourceFiles="@(MySourceFiles)" DestinationFiles="@(MySourceFiles->'$(TargetDir)%(Filename)%(Extension)')" />
   </Target>
   <Target Name="RemovingTempResx" AfterTargets="AfterBuild">
-    <Message Text="Removing temporary resx file" Importance="high"/>
+    <Message Text="Removing temporary resx file" Importance="high" />
     <Delete Files="$(TempResxFile)" />
   </Target>
 </Project>
diff --git a/lang/cs/Org.Apache.REEF.Client/Properties/AssemblyInfo.cs b/lang/cs/Org.Apache.REEF.Client/Properties/AssemblyInfo.cs
index 3c33105..3d70d6d 100644
--- a/lang/cs/Org.Apache.REEF.Client/Properties/AssemblyInfo.cs
+++ b/lang/cs/Org.Apache.REEF.Client/Properties/AssemblyInfo.cs
@@ -21,6 +21,11 @@
 [assembly: InternalsVisibleTo("Org.Apache.REEF.Tests")]
 [assembly: InternalsVisibleTo("Org.Apache.REEF.Client.Tests")]
 
+// Allow bridge access to internal APIs
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core")]
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Client")]
+
+
 // Allow NSubstitute to create proxy implementations
 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
 
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/ICompletedJob.cs b/lang/cs/Org.Apache.REEF.Common/Client/ICompletedJob.cs
new file mode 100644
index 0000000..17f6926
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/ICompletedJob.cs
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    /// <summary>
+    /// Event representing the completion of a job.
+    /// </summary>
+    public interface ICompletedJob : IIdentifiable
+    {
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/IFailedJob.cs b/lang/cs/Org.Apache.REEF.Common/Client/IFailedJob.cs
new file mode 100644
index 0000000..1dee514
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/IFailedJob.cs
@@ -0,0 +1,25 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Api;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    public interface IFailedJob : IIdentifiable, IFailure
+    {
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/IFailedRuntime.cs b/lang/cs/Org.Apache.REEF.Common/Client/IFailedRuntime.cs
new file mode 100644
index 0000000..35a4dc8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/IFailedRuntime.cs
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Api;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    /// <summary>
+    /// Error message that REEF Client gets when there is an error in REEF resourcemanager.
+    /// </summary>
+    public interface IFailedRuntime : IFailure
+    {
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/IJobMessage.cs b/lang/cs/Org.Apache.REEF.Common/Client/IJobMessage.cs
new file mode 100644
index 0000000..f396323
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/IJobMessage.cs
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    public interface IJobMessage : IIdentifiable, IMessage
+    {
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/IRunningJob.cs b/lang/cs/Org.Apache.REEF.Common/Client/IRunningJob.cs
new file mode 100644
index 0000000..b0935b8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/IRunningJob.cs
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    public interface IRunningJob : IIdentifiable, IDisposable
+    {
+        /// <summary>
+        /// Cancels the running Job.
+        /// </summary>
+        /// <param name="message">delivered along with cancel request</param>
+        void Dispose(byte[] message);
+
+        /// <summary>
+        /// Send message to the driver.
+        /// </summary>
+        /// <param name="message">to deliver to the driver</param>
+        void Send(byte[] message);
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/ISubmittedJob.cs b/lang/cs/Org.Apache.REEF.Common/Client/ISubmittedJob.cs
new file mode 100644
index 0000000..0295960
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/ISubmittedJob.cs
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    public interface ISubmittedJob : IIdentifiable
+    {
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/IWakeError.cs b/lang/cs/Org.Apache.REEF.Common/Client/IWakeError.cs
new file mode 100644
index 0000000..c2f0328
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/IWakeError.cs
@@ -0,0 +1,25 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using Org.Apache.REEF.Common.Api;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    public interface IWakeError : IIdentifiable, IFailure
+    {
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Client/LauncherStatus.cs b/lang/cs/Org.Apache.REEF.Common/Client/LauncherStatus.cs
new file mode 100644
index 0000000..768f868
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Client/LauncherStatus.cs
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Client
+{
+    public sealed class LauncherStatus
+    {
+        enum State
+        {
+            Init,
+            Submitted,
+            Running,
+            Completed,
+            Failed,
+            ForceClosed
+        }
+
+        public static readonly LauncherStatus InitStatus = new LauncherStatus(State.Init);
+        public static readonly LauncherStatus SubmittedStatus = new LauncherStatus(State.Submitted);
+        public static readonly LauncherStatus RunningStatus = new LauncherStatus(State.Running);
+        public static readonly LauncherStatus CompletedStatus = new LauncherStatus(State.Completed);
+        public static readonly LauncherStatus ForceCloseStatus = new LauncherStatus(State.ForceClosed);
+        public static readonly LauncherStatus FailedStatus = new LauncherStatus(State.Failed);
+
+        private readonly State _state;
+
+        public Optional<Exception> Error { get; }
+
+        public bool IsDone
+        {
+            get
+            {
+                switch (_state)
+                {
+                    case State.Failed:
+                    case State.Completed:
+                    case State.ForceClosed:
+                        return true;
+                    default:
+                        return false;
+                }
+            }
+        }
+
+        public bool IsSuccess => _state == State.Completed;
+
+        public bool IsRunning => _state == State.Running;
+
+        private LauncherStatus(State state) : this(state, null)
+        {
+        }
+
+        private LauncherStatus(State state, Exception ex)
+        {
+            _state = state;
+            Error = Optional<Exception>.OfNullable(ex);
+        }
+
+        public static LauncherStatus Failed(Exception ex)
+        {
+            return new LauncherStatus(State.Failed, ex);
+        }
+
+        public static LauncherStatus Failed(Optional<Exception> ex)
+        {
+            return new LauncherStatus(State.Failed, ex.OrElse(null));
+        }
+        public override bool Equals(Object other)
+        {
+            return this == other ||
+                   other is LauncherStatus && (other as LauncherStatus)._state == _state;
+        }
+
+        public override int GetHashCode()
+        {
+            return _state.GetHashCode();
+        }
+
+        public override String ToString()
+        {
+            if (Error.IsPresent())
+            {
+                return _state + "(" + Error.Value + ")";
+            }
+            else
+            {
+                return _state.ToString();
+            }
+        }
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Exceptions/NonSerializableJobException.cs b/lang/cs/Org.Apache.REEF.Common/Exceptions/NonSerializableJobException.cs
new file mode 100644
index 0000000..1e60e06
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/Exceptions/NonSerializableJobException.cs
@@ -0,0 +1,69 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Org.Apache.REEF.Common.Exceptions
+{
+    [Serializable]
+    public sealed class NonSerializableJobException : Exception
+    {
+
+        public string[] StackTrace { get;  }
+
+        internal static NonSerializableJobException UnableToSerialize(Exception originalException, SerializationException serializationException)
+        {
+            return new NonSerializableJobException(originalException, serializationException);
+        }
+
+        internal static NonSerializableJobException UnableToDeserialize(string exceptionString, SerializationException serializationException)
+        {
+            return new NonSerializableJobException(exceptionString, serializationException);
+        }
+
+        private NonSerializableJobException(Exception originalException, SerializationException serializationException)
+            : base(GetNonSerializableExceptionMessage(originalException), serializationException)
+        {
+            StackTrace = GetTraceString(originalException);
+        }
+
+        private NonSerializableJobException(string exceptionString, SerializationException serializationException)
+            : base(exceptionString, serializationException)
+        {
+            StackTrace = null;
+        }
+
+        private NonSerializableJobException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+
+        private static string[] GetTraceString(Exception ex)
+        {
+            var trace = new System.Diagnostics.StackTrace(ex, true);
+            return trace.GetFrames().Select(t => t.ToString()).ToArray();
+        }
+
+        private static string GetNonSerializableExceptionMessage(Exception e)
+        {
+            return string.Format("Unable to serialize the original Evaluator Exception. Original Exception.ToString(): {0}", e);
+        }
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Common/Properties/AssemblyInfo.cs b/lang/cs/Org.Apache.REEF.Common/Properties/AssemblyInfo.cs
index bf01667..7803821 100644
--- a/lang/cs/Org.Apache.REEF.Common/Properties/AssemblyInfo.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Properties/AssemblyInfo.cs
@@ -24,6 +24,10 @@
 // Common and Driver share APIs that should not be exposed to the user
 [assembly: InternalsVisibleTo("Org.Apache.REEF.Driver")]
 
+// Bridge needs access to internal objects
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Common")]
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Grpc")]
+
 // Common and IO share APIs that should not be exposed to the user
 [assembly: InternalsVisibleTo("Org.Apache.REEF.IO")]
 
diff --git a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskRuntime.cs b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskRuntime.cs
index 863b30d..83f6453 100644
--- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskRuntime.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskRuntime.cs
@@ -116,15 +116,24 @@
                     resultReturnedByTask = _userTask.Call(null);
                     Logger.Log(Level.Info, "Task Call Finished");
 
-                    // Run the handlers for `TaskStop`
-                    _currentStatus.RunTaskStopHandlers();
-
-                    // Log the result
-                    const Level resultLogLevel = Level.Verbose;
-                    if (Logger.IsLoggable(resultLogLevel) && resultReturnedByTask != null && resultReturnedByTask.Length > 0)
+                    if (!_currentStatus.HasEnded())
                     {
-                        Logger.Log(resultLogLevel,
-                            "Task running result:\r\n" + System.Text.Encoding.Default.GetString(resultReturnedByTask));
+                        Logger.Log(Level.Info, "Run the task stop handlers");
+                        _currentStatus.RunTaskStopHandlers();
+                        // Log the result
+                        const Level resultLogLevel = Level.Verbose;
+                        if (Logger.IsLoggable(resultLogLevel) && resultReturnedByTask != null &&
+                            resultReturnedByTask.Length > 0)
+                        {
+                            Logger.Log(resultLogLevel,
+                                "Task running result:\r\n" +
+                                System.Text.Encoding.Default.GetString(resultReturnedByTask));
+                        }
+                    }
+                    else
+                    {
+                        Logger.Log(Level.Info, "Task not running current state {0}", _currentStatus.State);
+                        returnResultToDriver = false;
                     }
                 }
                 catch (TaskStartHandlerException e)
@@ -149,7 +158,9 @@
                 {
                     try
                     {
+                        Logger.Log(Level.Info, "Try to dispose of task");
                         _userTask.Dispose();
+                        Logger.Log(Level.Info, "task diposed");
                     }
                     catch (Exception e)
                     {
@@ -216,7 +227,8 @@
             }
             catch (Exception e)
             {
-                Utilities.Diagnostics.Exceptions.CaughtAndThrow(e, Level.Error, "Error during Close.", Logger);
+                Logger.Log(Level.Info, "TaskRuntime::TaskClose exception", e);
+                _currentStatus.SetException(e);
             }
             finally
             {
@@ -247,8 +259,17 @@
             }
             
             // An Exception in suspend should crash the Evaluator.
-            OnNext(new SuspendEventImpl(message));
-            _currentStatus.SetSuspendRequested();
+            try
+            {
+                OnNext(new SuspendEventImpl(message));
+                _currentStatus.SetSuspendRequested();
+            }
+            catch (Exception e)
+            {
+                Logger.Log(Level.Info, "TaskRuntime::TaskSuspendHandler exception", e);
+                _currentStatus.SetException(e);
+                _userTask.Dispose();
+            }
         }
 
         public void Deliver(byte[] message)
@@ -259,7 +280,16 @@
                 return;
             }
 
-            OnNext(new DriverMessageImpl(message));
+            try
+            {
+                OnNext(new DriverMessageImpl(message));
+            }
+            catch (Exception e)
+            {
+                Logger.Log(Level.Error, "TaskRuntime::Deliver message excxeption", e);
+                _currentStatus.SetException(e);
+                _userTask.Dispose();
+            }
         }
 
         public void OnNext(ICloseEvent value)
diff --git a/lang/cs/Org.Apache.REEF.Driver/Defaults/DefaultTaskFailureHandler.cs b/lang/cs/Org.Apache.REEF.Driver/Defaults/DefaultTaskFailureHandler.cs
index 29a7d8e..16c6366 100644
--- a/lang/cs/Org.Apache.REEF.Driver/Defaults/DefaultTaskFailureHandler.cs
+++ b/lang/cs/Org.Apache.REEF.Driver/Defaults/DefaultTaskFailureHandler.cs
@@ -16,9 +16,9 @@
 // under the License.
 
 using System;
-using System.Globalization;
 using Org.Apache.REEF.Driver.Task;
 using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Logging;
 
 namespace Org.Apache.REEF.Driver.Defaults
 {
@@ -27,6 +27,8 @@
     /// </summary>
     public class DefaultTaskFailureHandler : IObserver<IFailedTask>
     {
+        private static readonly Logger Log = Logger.GetLogger(typeof(DefaultTaskFailureHandler));
+
         [Inject]
         public DefaultTaskFailureHandler()
         {
@@ -34,7 +36,17 @@
 
         public void OnNext(IFailedTask value)
         {
-            throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Task {0} has failed, and no handler was bound for IFailedTask", value.Id));
+            if (value.Data.IsPresent())
+            {
+                Log.Log(Level.Error, $"Task {value.Id} failed with exception", value.AsError());
+                throw new InvalidOperationException(
+                    $"Task {value.Id} has failed on {value.Message}, and no handler was bound for IFailedTask",
+                    value.AsError());
+            }
+
+            Log.Log(Level.Error, "Task {0} failed with NO exception information", value.Id);
+            throw new InvalidOperationException(
+                $"Task {value.Id} has failed on {value.Message}, and no handler was bound for IFailedTask");
         }
 
         public void OnError(Exception error)
diff --git a/lang/cs/Org.Apache.REEF.Driver/IDriverStopped.cs b/lang/cs/Org.Apache.REEF.Driver/IDriverStopped.cs
new file mode 100644
index 0000000..3c7c7e7
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Driver/IDriverStopped.cs
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+
+namespace Org.Apache.REEF.Driver
+{
+    /// <summary>
+    /// Stop event fired.
+    /// </summary>
+    public interface IDriverStopped
+    {
+        DateTime StopTime { get; }
+    }
+}
diff --git a/lang/cs/Org.Apache.REEF.Driver/Properties/AssemblyInfo.cs b/lang/cs/Org.Apache.REEF.Driver/Properties/AssemblyInfo.cs
index e7b4768..4a1e876 100644
--- a/lang/cs/Org.Apache.REEF.Driver/Properties/AssemblyInfo.cs
+++ b/lang/cs/Org.Apache.REEF.Driver/Properties/AssemblyInfo.cs
@@ -19,4 +19,5 @@
 
 // Allow the bridge access to `internal` APIs
 [assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge")]
-
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Common")]
+[assembly: InternalsVisibleTo("Org.Apache.REEF.Bridge.Core.Grpc")]
diff --git a/lang/cs/Org.Apache.REEF.Evaluator/Evaluator.cs b/lang/cs/Org.Apache.REEF.Evaluator/Evaluator.cs
index ed9ae1c..60f8407 100644
--- a/lang/cs/Org.Apache.REEF.Evaluator/Evaluator.cs
+++ b/lang/cs/Org.Apache.REEF.Evaluator/Evaluator.cs
@@ -89,6 +89,7 @@
                     .BindSetEntry<RuntimeStartHandler, EvaluatorRuntime, IObserver<RuntimeStart>>()
                     .BindSetEntry<RuntimeStopHandler, EvaluatorRuntime, IObserver<RuntimeStop>>()
                     .Build();
+            logger.Log(Level.Info, "Creating the Evaluator instance");
             var evaluator = injector.ForkInjector(rootEvaluatorConfiguration).GetInstance<Evaluator>();
 
             evaluator.Run();
@@ -140,9 +141,10 @@
                 Utilities.Diagnostics.Exceptions.Throw(new FileNotFoundException("cannot find file " + evaluatorConfigFile), logger);
             }
 
+            logger.Log(Level.Info, "Assembly name for evaluator configuration: {0}", typeof(ApplicationIdentifier).Assembly.GetName().Name);
             AvroConfigurationSerializer serializer = new AvroConfigurationSerializer();
             var classHierarchy = TangFactory.GetTang()
-                .GetClassHierarchy(new string[] { typeof(ApplicationIdentifier).GetTypeInfo().Assembly.GetName().Name });
+                .GetClassHierarchy(new string[] { typeof(ApplicationIdentifier).Assembly.GetName().Name });
             var evaluatorConfiguration = serializer.FromFile(evaluatorConfigFile, classHierarchy);
 
             logger.Log(Level.Info, 
diff --git a/lang/cs/Org.Apache.REEF.IO.Tests/TestAzureBlobFileSystemE2E.cs b/lang/cs/Org.Apache.REEF.IO.Tests/TestAzureBlobFileSystemE2E.cs
index 7ee1268..cd9d2c2 100644
--- a/lang/cs/Org.Apache.REEF.IO.Tests/TestAzureBlobFileSystemE2E.cs
+++ b/lang/cs/Org.Apache.REEF.IO.Tests/TestAzureBlobFileSystemE2E.cs
@@ -57,7 +57,8 @@
             _fileSystem = TangFactory.GetTang().NewInjector(conf).GetInstance<AzureBlobFileSystem>();
             _client = CloudStorageAccount.Parse(ConnectionString).CreateCloudBlobClient();
             _container = _client.GetContainerReference(defaultContainerName);
-            _container.CreateIfNotExists();
+            var t = _container.CreateIfNotExistsAsync();
+            t.Wait();
         }
 
         public void Dispose()
diff --git a/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestCloseTask.cs b/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestCloseTask.cs
index 5f08b56..86c06ea 100644
--- a/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestCloseTask.cs
+++ b/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestCloseTask.cs
@@ -98,7 +98,7 @@
         [Fact]
         public void TestTaskWithNoCloseHandlerOnLocalRuntime()
         {
-            const string closeHandlerNoBound = "ExceptionCaught TaskCloseHandlerNotBoundException";
+            const string closeHandlerNoBound = "TaskCloseHandlerNotBoundException";
 
             string testFolder = DefaultRuntimeFolder + Guid.NewGuid().ToString("N").Substring(0, 4);
             TestRun(DriverConfigurations(DisposeMessageFromDriver, GetTaskConfigurationForNoCloseHandlerTask()), typeof(CloseTaskTestDriver), 1, "testStopTaskWithNoCloseHandler", "local", testFolder);
diff --git a/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestDisposeTasks.cs b/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestDisposeTasks.cs
deleted file mode 100644
index f7ebd2c..0000000
--- a/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/TestDisposeTasks.cs
+++ /dev/null
@@ -1,297 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading;
-using Org.Apache.REEF.Common.Context;
-using Org.Apache.REEF.Common.Tasks;
-using Org.Apache.REEF.Common.Tasks.Events;
-using Org.Apache.REEF.Driver;
-using Org.Apache.REEF.Driver.Context;
-using Org.Apache.REEF.Driver.Evaluator;
-using Org.Apache.REEF.Driver.Task;
-using Org.Apache.REEF.Tang.Annotations;
-using Org.Apache.REEF.Tang.Implementations.Configuration;
-using Org.Apache.REEF.Tang.Implementations.Tang;
-using Org.Apache.REEF.Tang.Interface;
-using Org.Apache.REEF.Tang.Util;
-using Org.Apache.REEF.Tests.Functional.Bridge.Exceptions;
-using Org.Apache.REEF.Utilities.Logging;
-using Xunit;
-
-namespace Org.Apache.REEF.Tests.Functional.Bridge
-{
-    [Collection("FunctionalTests")]
-    public class TestDisposeTasks : ReefFunctionalTest
-    {
-        private static readonly Logger Logger = Logger.GetLogger(typeof(TestDisposeTasks));
-
-        private const string ExitByReturn = "ExitByReturn";
-        private const string ExitByException = "ExitByException";
-        private const string TaskIsDisposed = "TaskIsDisposed";
-        private const string TaskKilledByDriver = "TaskKilledByDriver";
-        private const string TaskId = "TaskId";
-        private const string ContextId = "ContextId";
-
-        /// <summary>
-        /// Test scenario: Task returned properly then disposed
-        /// </summary>
-        [Fact]
-        public void TestDisposeInTaskNormalReturnOnLocalRuntime()
-        {
-            string testFolder = DefaultRuntimeFolder + TestId;
-            TestRun(DriverConfigurations(1), typeof(TestDisposeTasks), 1, "TestDisposeTasks", "local", testFolder);
-            ValidateSuccessForLocalRuntime(1, 0, 0, testFolder);
-            var messages = new List<string> { TaskIsDisposed };
-            ValidateMessageSuccessfullyLogged(messages, "Node-*", EvaluatorStdout, testFolder, 1);
-            ////CleanUp(testFolder);
-        }
-
-        /// <summary>
-        /// Test scenario: Task is enforced to close after receiving close event
-        /// </summary>
-        [Fact]
-        public void TestDisposeInTaskExceptionOnLocalRuntime()
-        {
-            string testFolder = DefaultRuntimeFolder + TestId;
-            TestRun(DriverConfigurations(2), typeof(TestDisposeTasks), 1, "TestDisposeTasks", "local", testFolder);
-            ValidateSuccessForLocalRuntime(0, 0, 1, testFolder);
-            var messages = new List<string> { TaskIsDisposed };
-            ValidateMessageSuccessfullyLogged(messages, "Node-*", EvaluatorStdout, testFolder, 1);
-            CleanUp(testFolder);
-        }
-
-        /// <summary>
-        /// Test scenario: Dispose context while the task is still running.
-        /// </summary>
-        [Fact]
-        public void TestDisposeFromContextInRunningOnLocalRuntime()
-        {
-            string testFolder = DefaultRuntimeFolder + TestId;
-            TestRun(DriverConfigurations(3), typeof(TestDisposeTasks), 1, "TestDisposeTasks", "local", testFolder);
-            ValidateSuccessForLocalRuntime(1, 0, 0, testFolder);
-            var messages = new List<string>();
-            messages.Add(TaskIsDisposed);
-            ValidateMessageSuccessfullyLogged(messages, "Node-*", EvaluatorStdout, testFolder, 1);
-            CleanUp(testFolder);
-        }
-
-        /// <summary>
-        /// Driver configuration for the test driver
-        /// </summary>
-        /// <returns></returns>
-        public IConfiguration DriverConfigurations(int taskNumber)
-        {
-            var taskIdConfig = TangFactory.GetTang()
-                .NewConfigurationBuilder()
-                .BindStringNamedParam<TaskNumber>(taskNumber.ToString())
-                .Build();
-
-            var driverConfig = DriverConfiguration.ConfigurationModule
-                .Set(DriverConfiguration.OnDriverStarted, GenericType<DisposeTaskTestDriver>.Class)
-                .Set(DriverConfiguration.OnEvaluatorAllocated, GenericType<DisposeTaskTestDriver>.Class)
-                .Set(DriverConfiguration.OnContextActive, GenericType<DisposeTaskTestDriver>.Class)
-                .Set(DriverConfiguration.OnTaskRunning, GenericType<DisposeTaskTestDriver>.Class)
-                .Set(DriverConfiguration.OnTaskCompleted, GenericType<DisposeTaskTestDriver>.Class)
-                .Set(DriverConfiguration.OnEvaluatorFailed, GenericType<DisposeTaskTestDriver>.Class)
-                .Build();
-
-            return Configurations.Merge(taskIdConfig, driverConfig);
-        }
-
-        /// <summary>
-        /// Test driver
-        /// </summary>
-        private sealed class DisposeTaskTestDriver :
-            IObserver<IDriverStarted>,
-            IObserver<IAllocatedEvaluator>,
-            IObserver<IActiveContext>,
-            IObserver<ICompletedTask>,
-            IObserver<IFailedEvaluator>,
-            IObserver<IRunningTask>            
-        {
-            private readonly IEvaluatorRequestor _requestor;            
-            private readonly string _taskNumber;
-
-            [Inject]
-            private DisposeTaskTestDriver(IEvaluatorRequestor evaluatorRequestor,
-                [Parameter(typeof(TaskNumber))] string taskNumber)
-            {
-                _requestor = evaluatorRequestor;
-                _taskNumber = taskNumber;
-            }
-
-            public void OnNext(IDriverStarted value)
-            {
-                _requestor.Submit(_requestor.NewBuilder().SetNumber(1).Build());
-            }
-
-            public void OnNext(IAllocatedEvaluator value)
-            {
-                value.SubmitContext(
-                    ContextConfiguration.ConfigurationModule
-                        .Set(ContextConfiguration.Identifier, ContextId)
-                        .Build());
-            }
-
-            public void OnNext(IActiveContext value)
-            {
-                value.SubmitTask(GetTaskConfigurationForCloseTask(TaskId + _taskNumber));
-            }
-
-            public void OnNext(ICompletedTask value)
-            {
-                Logger.Log(Level.Info, "Task completed: " + value.Id);
-                Assert.Equal(TaskId + "1", value.Id);
-                value.ActiveContext.Dispose();
-            }
-
-            /// <summary>
-            /// Verify when exception is shown in task, IFailedTask will be received here with the message set in the task
-            /// And verify the context associated with the failed task is the same as the context that the task was submitted
-            /// </summary>
-            /// <param name="value"></param>
-            public void OnNext(IFailedEvaluator value)
-            {
-                Assert.True(value.FailedTask.IsPresent());
-                Assert.Equal(TaskId + "2", value.FailedTask.Value.Id);
-
-                var e = value.EvaluatorException.InnerException;
-                Logger.Log(Level.Error, "In IFailedTask: e.type: {0}, e.message: {1}.", e.GetType(), e.Message);
-
-                Assert.Equal(typeof(TestSerializableException), e.GetType());
-                Assert.Equal(TaskKilledByDriver, e.Message);
-            }
-
-            /// <summary>
-            /// Task1: Close task and expect it to return from Call()
-            /// Task2: Close the task and expect it throw exception
-            /// Task3: Let context Dispose to close a running task and make sure the task is disposed
-            /// </summary>
-            /// <param name="value"></param>
-            public void OnNext(IRunningTask value)
-            {
-                Logger.Log(Level.Info, "Task running: " + value.Id);
-                switch (value.Id)
-                {
-                    case TaskId + "1":
-                        value.Dispose(Encoding.UTF8.GetBytes(ExitByReturn));
-                        break;
-                    case TaskId + "2":
-                        value.Dispose(Encoding.UTF8.GetBytes(ExitByException));
-                        break;
-                    case TaskId + "3":
-                        value.ActiveContext.Dispose();
-                        break;
-                }
-            }
-
-            public void OnCompleted()
-            {
-                throw new NotImplementedException();
-            }
-
-            public void OnError(Exception error)
-            {
-                throw new NotImplementedException();
-            }
-
-            private static IConfiguration GetTaskConfigurationForCloseTask(string taskId)
-            {
-                return TaskConfiguration.ConfigurationModule
-                    .Set(TaskConfiguration.Identifier, taskId)
-                    .Set(TaskConfiguration.Task, GenericType<CloseAndDisposeTask>.Class)
-                    .Set(TaskConfiguration.OnClose, GenericType<CloseAndDisposeTask>.Class)
-                    .Build();
-            }
-        }
-
-        private sealed class CloseAndDisposeTask : ITask, IObserver<ICloseEvent>
-        {
-            private readonly CountdownEvent _suspendSignal = new CountdownEvent(1);
-            private int _disposed = 0;
-
-            [Inject]
-            private CloseAndDisposeTask()
-            {
-            }
-
-            public byte[] Call(byte[] memento)
-            {
-                Logger.Log(Level.Info, "Hello in CloseAndDisposeTask");
-                _suspendSignal.Wait();
-                return null;
-            }
-
-            public void Dispose()
-            {
-                if (Interlocked.Exchange(ref _disposed, 1) == 0)
-                {
-                    Logger.Log(Level.Info, TaskIsDisposed);
-                }
-            }
-
-            /// <summary>
-            /// Case 1: if message is ExitByReturn, signal the Call() to make the task return.  
-            /// Case 2: if message is ExitByException, throw exception to expect the driver to receive FailedTask. 
-            /// Otherwise do nothing, expecting TaskRuntime to dispose the task. 
-            /// </summary>
-            /// <param name="closeEvent"></param>
-            public void OnNext(ICloseEvent closeEvent)
-            {
-                if (closeEvent.Value != null)
-                {
-                    if (closeEvent.Value.IsPresent())
-                    {
-                        string msg = Encoding.UTF8.GetString(closeEvent.Value.Value);
-                        Logger.Log(Level.Info, "Closed event received in task:" + msg);
-
-                        if (msg.Equals(ExitByReturn))
-                        {
-                            _suspendSignal.Signal();
-                        }
-                        else if (msg.Equals(ExitByException))
-                        {
-                            throw new TestSerializableException(TaskKilledByDriver);
-                        }
-                    }
-                    else
-                    {
-                        Logger.Log(Level.Info, "Closed event received in task with no message");
-                    }
-                }
-            }
-
-            public void OnCompleted()
-            {
-                throw new NotImplementedException();
-            }
-
-            public void OnError(Exception error)
-            {
-                throw new NotImplementedException();
-            }
-        }
-
-        [NamedParameter]
-        private class TaskNumber : Name<string>
-        {            
-        }        
-    }
-}
diff --git a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ReceiveTaskMessageExceptionTest.cs b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ReceiveTaskMessageExceptionTest.cs
index 59c57b0..8985e9d 100644
--- a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ReceiveTaskMessageExceptionTest.cs
+++ b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ReceiveTaskMessageExceptionTest.cs
@@ -54,11 +54,11 @@
                 .Set(DriverConfiguration.OnEvaluatorAllocated, GenericType<TestReceiveTaskMessageExceptionDriver>.Class)
                 .Set(DriverConfiguration.OnEvaluatorFailed, GenericType<TestReceiveTaskMessageExceptionDriver>.Class)
                 .Set(DriverConfiguration.OnTaskRunning, GenericType<TestReceiveTaskMessageExceptionDriver>.Class)
+                .Set(DriverConfiguration.OnTaskFailed, GenericType<TestReceiveTaskMessageExceptionDriver>.Class)
                 .Build(),
                 typeof(TestReceiveTaskMessageExceptionDriver), 1, "ReceiveTaskMessageExceptionTest", "local", testFolder);
 
-            ValidateSuccessForLocalRuntime(0, 0, 1, testFolder);
-            ValidateMessageSuccessfullyLoggedForDriver(ReceivedFailedEvaluator, testFolder);
+            ValidateSuccessForLocalRuntime(1, 1, 0, testFolder);
             CleanUp(testFolder);
         }
 
@@ -66,7 +66,8 @@
             IObserver<IDriverStarted>,
             IObserver<IAllocatedEvaluator>,
             IObserver<IFailedEvaluator>,
-            IObserver<IRunningTask>
+            IObserver<IRunningTask>,
+            IObserver<IFailedTask>
         {
             private readonly IEvaluatorRequestor _requestor;
 
@@ -91,6 +92,11 @@
                         .Build());
             }
 
+            public void OnNext(IFailedTask task)
+            {
+                task.GetActiveContext().Value.Dispose();
+            }
+
             /// <summary>
             /// Throwing an Exception in a Driver message handler will result in a Failed Evaluator.
             /// We check for the Task ID and Exception type here.
diff --git a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskCloseExceptionTest.cs b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskCloseExceptionTest.cs
index 364c81b..429c2d7 100644
--- a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskCloseExceptionTest.cs
+++ b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskCloseExceptionTest.cs
@@ -5,9 +5,9 @@
 // to you under the Apache License, Version 2.0 (the
 // "License"); you may not use this file except in compliance
 // with the License.  You may obtain a copy of the License at
-// 
+//
 //   http://www.apache.org/licenses/LICENSE-2.0
-// 
+//
 // Unless required by applicable law or agreed to in writing,
 // software distributed under the License is distributed on an
 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -15,11 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-using System;
-using System.Collections.Generic;
 using Org.Apache.REEF.Common.Tasks;
 using Org.Apache.REEF.Common.Tasks.Events;
 using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
 using Org.Apache.REEF.Driver.Evaluator;
 using Org.Apache.REEF.Driver.Task;
 using Org.Apache.REEF.Tang.Annotations;
@@ -29,12 +28,13 @@
 using Org.Apache.REEF.Tests.Functional.Common.Task;
 using Org.Apache.REEF.Tests.Functional.Common.Task.Handlers;
 using Org.Apache.REEF.Utilities.Logging;
+using System;
 using Xunit;
 
 namespace Org.Apache.REEF.Tests.Functional.Failure.User
 {
     /// <summary>
-    /// This test class contains a test that validates that an Exception in the 
+    /// This test class contains a test that validates that an Exception in the
     /// TaskCloseHandler causes a FailedTask event in the Driver.
     /// </summary>
     [Collection("FunctionalTests")]
@@ -56,18 +56,12 @@
             TestRun(DriverConfiguration.ConfigurationModule
                 .Set(DriverConfiguration.OnDriverStarted, GenericType<TaskCloseExceptionTestDriver>.Class)
                 .Set(DriverConfiguration.OnEvaluatorAllocated, GenericType<TaskCloseExceptionTestDriver>.Class)
-                .Set(DriverConfiguration.OnEvaluatorFailed, GenericType<TaskCloseExceptionTestDriver>.Class)
+                .Set(DriverConfiguration.OnTaskFailed, GenericType<TaskCloseExceptionTestDriver>.Class)
                 .Set(DriverConfiguration.OnTaskRunning, GenericType<TaskCloseExceptionTestDriver>.Class)
+                .Set(DriverConfiguration.OnContextClosed, GenericType<TaskCloseExceptionTestDriver>.Class)
                 .Build(), typeof(TaskCloseExceptionTestDriver), 1, "testCloseTaskWithExceptionOnLocalRuntime", "local", testFolder);
 
-            var driverMessages = new List<string>
-            {
-                FailedEvaluatorReceived
-            };
-
-            ValidateSuccessForLocalRuntime(numberOfContextsToClose: 0, numberOfEvaluatorsToFail: 1, testFolder: testFolder);
-            ValidateMessagesSuccessfullyLoggedForDriver(driverMessages, testFolder, 1);
-            ValidateMessageSuccessfullyLogged(driverMessages, "driver", DriverStdout, testFolder, 1);
+            ValidateSuccessForLocalRuntime(numberOfContextsToClose: 2, numberOfTasksToFail: 2, numberOfEvaluatorsToFail: 0, testFolder: testFolder);
             CleanUp(testFolder);
         }
 
@@ -75,7 +69,8 @@
             IObserver<IDriverStarted>,
             IObserver<IAllocatedEvaluator>,
             IObserver<IRunningTask>,
-            IObserver<IFailedEvaluator>
+            IObserver<IFailedTask>,
+            IObserver<IClosedContext>
         {
             private static readonly string TaskId = "TaskId";
 
@@ -92,6 +87,10 @@
                 _requestor.Submit(_requestor.NewBuilder().Build());
             }
 
+            public void OnNext(IClosedContext context)
+            {
+            }
+
             public void OnNext(IAllocatedEvaluator value)
             {
                 // submit the first Task.
@@ -110,34 +109,9 @@
                 }
             }
 
-            public void OnNext(IFailedEvaluator value)
+            public void OnNext(IFailedTask value)
             {
-                Assert.True(value.FailedTask.IsPresent());
-                var failedTask = value.FailedTask.Value;
-
-                Assert.Equal(TaskId, failedTask.Id);
-
-                // Check that Exceptions are deserialized correctly.
-                var ex = value.EvaluatorException.InnerException;
-                if (ex == null)
-                {
-                    throw new Exception("Exception was not expected to be null.");
-                }
-
-                var taskCloseEx = ex as TestSerializableException;
-
-                if (taskCloseEx == null)
-                {
-                    throw new Exception("Expected Exception to be of type TaskCloseExceptionTestException, but instead got type " + ex.GetType().Name);
-                }
-
-                if (taskCloseEx.Message != TaskCloseExceptionMessage)
-                {
-                    throw new Exception(
-                        "Expected message to be " + TaskCloseExceptionMessage + " but instead got " + taskCloseEx.Message + ".");
-                }
-
-                Logger.Log(Level.Info, FailedEvaluatorReceived);
+                value.GetActiveContext().Value.Dispose();
             }
 
             public void OnError(Exception error)
diff --git a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskSuspendExceptionTest.cs b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskSuspendExceptionTest.cs
deleted file mode 100644
index 2ce135a..0000000
--- a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/TaskSuspendExceptionTest.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-// 
-//   http://www.apache.org/licenses/LICENSE-2.0
-// 
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-using System;
-using System.Collections.Generic;
-using Org.Apache.REEF.Common.Tasks;
-using Org.Apache.REEF.Common.Tasks.Events;
-using Org.Apache.REEF.Driver;
-using Org.Apache.REEF.Driver.Evaluator;
-using Org.Apache.REEF.Driver.Task;
-using Org.Apache.REEF.Tang.Annotations;
-using Org.Apache.REEF.Tang.Util;
-using Org.Apache.REEF.Tests.Functional.Bridge.Exceptions;
-using Org.Apache.REEF.Tests.Functional.Common;
-using Org.Apache.REEF.Tests.Functional.Common.Task;
-using Org.Apache.REEF.Tests.Functional.Common.Task.Handlers;
-using Org.Apache.REEF.Utilities.Logging;
-using Xunit;
-
-namespace Org.Apache.REEF.Tests.Functional.Failure.User
-{
-    /// <summary>
-    /// This test class contains a test that validates that an Exception in the 
-    /// TaskSuspendHandler causes a FailedEvaluator event in the Driver.
-    /// </summary>
-    [Collection("FunctionalTests")]
-    public sealed class TaskSuspendExceptionTest : ReefFunctionalTest
-    {
-        private static readonly Logger Logger = Logger.GetLogger(typeof(TaskSuspendExceptionTest));
-
-        private const string TaskSuspendExceptionMessage = "TaskSuspendExceptionMessage";
-        private const string InitialTaskPreWaitMessage = "InitialTaskPreWaitMessage";
-        private const string InitialTaskPostWaitMessage = "InitialTaskPostWaitMessage";
-        private const string FailedEvaluatorReceived = "FailedEvaluatorReceived";
-        private const string TaskSuspensionMessage = "TaskSuspensionMessage";
-
-        /// <summary>
-        /// This test validates that an Exception in the TaskSuspendHandler causes a FailedEvaluator event.
-        /// </summary>
-        [Fact]
-        public void TestSuspendTaskWithExceptionOnLocalRuntime()
-        {
-            string testFolder = DefaultRuntimeFolder + Guid.NewGuid().ToString("N").Substring(0, 4);
-            TestRun(DriverConfiguration.ConfigurationModule
-                .Set(DriverConfiguration.OnDriverStarted, GenericType<TaskSuspendExceptionTestDriver>.Class)
-                .Set(DriverConfiguration.OnEvaluatorAllocated, GenericType<TaskSuspendExceptionTestDriver>.Class)
-                .Set(DriverConfiguration.OnEvaluatorFailed, GenericType<TaskSuspendExceptionTestDriver>.Class)
-                .Set(DriverConfiguration.OnTaskRunning, GenericType<TaskSuspendExceptionTestDriver>.Class)
-                .Build(), typeof(TaskSuspendExceptionTestDriver), 1, "testSuspendTaskWithExceptionOnLocalRuntime", "local", testFolder);
-
-            var driverMessages = new List<string>
-            {
-                TaskSuspensionMessage,
-                FailedEvaluatorReceived
-            };
-
-            ValidateMessagesSuccessfullyLoggedForDriver(driverMessages, testFolder, 1);
-            ValidateMessageSuccessfullyLogged(driverMessages, "driver", DriverStdout, testFolder, 1);
-
-            var evaluatorMessages = new List<string> { InitialTaskPreWaitMessage };
-            ValidateMessageSuccessfullyLogged(evaluatorMessages, "Node-*", EvaluatorStdout, testFolder, 1);
-            CleanUp(testFolder);
-        }
-
-        private sealed class TaskSuspendExceptionTestDriver :
-            IObserver<IDriverStarted>,
-            IObserver<IAllocatedEvaluator>,
-            IObserver<IRunningTask>,
-            IObserver<IFailedEvaluator>
-        {
-            private static readonly string TaskId = "TaskId";
-
-            private readonly IEvaluatorRequestor _requestor;
-
-            [Inject]
-            private TaskSuspendExceptionTestDriver(IEvaluatorRequestor requestor)
-            {
-                _requestor = requestor;
-            }
-
-            public void OnNext(IDriverStarted value)
-            {
-                _requestor.Submit(_requestor.NewBuilder().Build());
-            }
-
-            public void OnNext(IAllocatedEvaluator value)
-            {
-                // submit the first Task.
-                value.SubmitTask(TaskConfiguration.ConfigurationModule
-                        .Set(TaskConfiguration.Identifier, TaskId)
-                        .Set(TaskConfiguration.Task, GenericType<TaskSuspendExceptionTask>.Class)
-                        .Set(TaskConfiguration.OnSuspend, GenericType<TaskSuspendHandlerWithException>.Class)
-                        .Build());
-            }
-
-            public void OnNext(IRunningTask value)
-            {
-                if (value.Id == TaskId)
-                {
-                    Logger.Log(Level.Info, TaskSuspensionMessage);
-                    value.Suspend();
-                }
-            }
-
-            public void OnNext(IFailedEvaluator value)
-            {
-                Assert.True(value.FailedTask.IsPresent());
-                Assert.Equal(TaskId, value.FailedTask.Value.Id);
-                Assert.True(value.EvaluatorException.InnerException is TestSerializableException);
-                Assert.Equal(TaskSuspendExceptionMessage, value.EvaluatorException.InnerException.Message);
-                Logger.Log(Level.Info, FailedEvaluatorReceived);
-            }
-
-            public void OnError(Exception error)
-            {
-                throw new NotImplementedException();
-            }
-
-            public void OnCompleted()
-            {
-                throw new NotImplementedException();
-            }
-        }
-
-        private sealed class TaskSuspendExceptionTask : WaitingTask
-        {
-            [Inject]
-            private TaskSuspendExceptionTask(EventMonitor monitor)
-                : base(monitor, InitialTaskPreWaitMessage, InitialTaskPostWaitMessage)
-            {
-            }
-        }
-
-        private sealed class TaskSuspendHandlerWithException : ExceptionThrowingHandler<ISuspendEvent>
-        {
-            [Inject]
-            private TaskSuspendHandlerWithException(EventMonitor monitor)
-                : base(
-                    new TestSerializableException(TaskSuspendExceptionMessage),
-                    close => { monitor.Signal(); })
-            {
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/lang/cs/Org.Apache.REEF.Tests/Functional/FaultTolerant/TestResubmitTask.cs b/lang/cs/Org.Apache.REEF.Tests/Functional/FaultTolerant/TestResubmitTask.cs
index 675dc5d..9e8cd38 100644
--- a/lang/cs/Org.Apache.REEF.Tests/Functional/FaultTolerant/TestResubmitTask.cs
+++ b/lang/cs/Org.Apache.REEF.Tests/Functional/FaultTolerant/TestResubmitTask.cs
@@ -75,7 +75,7 @@
         {
             string testFolder = DefaultRuntimeFolder + TestId;
             TestRun(DriverConfigurations(), typeof(ResubmitTaskTestDriver), 2, "TestResubimitTask", "local", testFolder);
-            ValidateSuccessForLocalRuntime(1, 0, 1, testFolder);
+            ValidateSuccessForLocalRuntime(2, 1, 0, testFolder);
             CleanUp(testFolder);
         }
 
@@ -91,7 +91,7 @@
                 .Set(DriverConfiguration.OnContextActive, GenericType<ResubmitTaskTestDriver>.Class)
                 .Set(DriverConfiguration.OnTaskRunning, GenericType<ResubmitTaskTestDriver>.Class)
                 .Set(DriverConfiguration.OnTaskCompleted, GenericType<ResubmitTaskTestDriver>.Class)
-                .Set(DriverConfiguration.OnEvaluatorFailed, GenericType<ResubmitTaskTestDriver>.Class)
+                .Set(DriverConfiguration.OnTaskFailed, GenericType<ResubmitTaskTestDriver>.Class)
                 .Build();
         }
 
@@ -103,14 +103,13 @@
             IObserver<IAllocatedEvaluator>,
             IObserver<IActiveContext>,
             IObserver<ICompletedTask>,
-            IObserver<IFailedEvaluator>,
+            IObserver<IFailedTask>,
             IObserver<IRunningTask>
         {
             private readonly IEvaluatorRequestor _requestor;
             private const string TaskId = "TaskId";
             private int _taskNumber = 1;
             private const string ContextId = "ContextId";
-            private int _contextNumber = 1;
             private readonly IDictionary<string, string> _taskContextMapping = new Dictionary<string, string>();
             private readonly object _lock = new object();
 
@@ -127,55 +126,33 @@
 
             public void OnNext(IAllocatedEvaluator value)
             {
-                lock (_lock)
-                {
-                    value.SubmitContext(
-                        ContextConfiguration.ConfigurationModule
-                            .Set(ContextConfiguration.Identifier, ContextId + _contextNumber)
-                            .Build());
-                    _contextNumber++;
-                }
+                value.SubmitContext(
+                    ContextConfiguration.ConfigurationModule
+                        .Set(ContextConfiguration.Identifier, ContextId)
+                        .Build());
             }
 
             public void OnNext(IActiveContext value)
             {
-                lock (_lock)
-                {
-                    value.SubmitTask(GetTaskConfigurationForCloseTask(TaskId + _taskNumber));
-                    _taskContextMapping.Add(TaskId + _taskNumber, value.Id);
-                    _taskNumber++;
-                }
+                value.SubmitTask(GetTaskConfigurationForCloseTask(TaskId + _taskNumber));
+                _taskContextMapping.Add(TaskId + _taskNumber, value.Id);
+                _taskNumber++;
             }
 
             public void OnNext(ICompletedTask value)
             {
                 Logger.Log(Level.Info, "Task completed: " + value.Id);
-                VerifyContextTaskMapping(value.Id, value.ActiveContext.Id);
                 value.ActiveContext.Dispose();
             }
 
             /// <summary>
             /// Verify when exception is shown in TaskCloseHandler, IFailedEvaluator will be received here with the message set in the task
             /// </summary>
-            public void OnNext(IFailedEvaluator value)
+            public void OnNext(IFailedTask value)
             {
-                Assert.True(value.FailedTask.IsPresent());
-                var failedExeption = value.EvaluatorException.InnerException;
-                Assert.Contains(TaskKilledByDriver, failedExeption.Message);
-
-                Logger.Log(Level.Error, "In IFailedEvaluator: " + failedExeption);
-
-                VerifyContextTaskMapping(value.FailedTask.Value.Id, value.FailedContexts.Single().Id);
-            }
-
-            private void VerifyContextTaskMapping(string taskId, string contextId)
-            {
-                lock (_lock)
-                {
-                    string expectedContextId;
-                    _taskContextMapping.TryGetValue(taskId, out expectedContextId);
-                    Assert.Equal(expectedContextId, contextId);
-                }
+                value.GetActiveContext().Value.SubmitTask(GetTaskConfigurationForCloseTask(TaskId + _taskNumber));
+                _taskContextMapping.Add(TaskId + _taskNumber, value.Id);
+                _taskNumber++;
             }
 
             /// <summary>
diff --git a/lang/cs/Org.Apache.REEF.Wake/Remote/Parameters/TcpPortRangeStart.cs b/lang/cs/Org.Apache.REEF.Wake/Remote/Parameters/TcpPortRangeStart.cs
index 2f3352a..40db7f3 100644
--- a/lang/cs/Org.Apache.REEF.Wake/Remote/Parameters/TcpPortRangeStart.cs
+++ b/lang/cs/Org.Apache.REEF.Wake/Remote/Parameters/TcpPortRangeStart.cs
@@ -19,7 +19,7 @@
 
 namespace Org.Apache.REEF.Wake.Remote.Parameters
 {
-    [NamedParameter(Documentation = "Port number range start for listening on tcp ports", DefaultValue = "8900")]
+    [NamedParameter(Documentation = "Port number range start for listening on tcp ports", DefaultValue = "10000")]
     public sealed class TcpPortRangeStart : Name<int>
     {
     }
diff --git a/lang/cs/Org.Apache.REEF.sln b/lang/cs/Org.Apache.REEF.sln
index 631442c..4a9b52f 100644
--- a/lang/cs/Org.Apache.REEF.sln
+++ b/lang/cs/Org.Apache.REEF.sln
@@ -76,144 +76,262 @@
 EndProject

 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.CLR", "Org.Apache.REEF.Bridge.CLR\Org.Apache.REEF.Bridge.CLR.csproj", "{81575917-C673-4E6F-9CF1-0DD35FC5E717}"

 EndProject

+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.Core.Common", "Org.Apache.REEF.Bridge.Core.Common\Org.Apache.REEF.Bridge.Core.Common.csproj", "{5961DBD3-9A65-4B9C-B9D2-7139954F3163}"

+EndProject

+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.Core.HelloREEF", "Org.Apache.REEF.Bridge.Core.HelloREEF\Org.Apache.REEF.Bridge.Core.HelloREEF.csproj", "{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}"

+EndProject

+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.Core.Grpc", "Org.Apache.REEF.Bridge.Core.Grpc\Org.Apache.REEF.Bridge.Core.Grpc.csproj", "{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}"

+	ProjectSection(ProjectDependencies) = postProject

+		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E} = {448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}

+	EndProjectSection

+EndProject

+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.Core.Driver", "Org.Apache.REEF.Bridge.Core.Driver\Org.Apache.REEF.Bridge.Core.Driver.csproj", "{848458F1-0E94-46A2-A35D-03F96286182A}"

+EndProject

+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.Core.Tests", "Org.Apache.REEF.Bridge.Core.Tests\Org.Apache.REEF.Bridge.Core.Tests.csproj", "{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}"

+EndProject

+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Org.Apache.REEF.Bridge.Core.Proto", "Org.Apache.REEF.Bridge.Core.Proto\Org.Apache.REEF.Bridge.Core.Proto.csproj", "{CA34E32B-0028-484C-B71C-75FE38036F08}"

+EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Debug|x64 = Debug|x64

+		Release|Any CPU = Release|Any CPU

 		Release|x64 = Release|x64

 	EndGlobalSection

 	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{6C7325D1-EBB6-4642-B34F-B66F46152230}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{6C7325D1-EBB6-4642-B34F-B66F46152230}.Debug|x64.ActiveCfg = Debug|x64

 		{6C7325D1-EBB6-4642-B34F-B66F46152230}.Debug|x64.Build.0 = Debug|x64

+		{6C7325D1-EBB6-4642-B34F-B66F46152230}.Release|Any CPU.ActiveCfg = Release|x64

 		{6C7325D1-EBB6-4642-B34F-B66F46152230}.Release|x64.ActiveCfg = Release|x64

 		{6C7325D1-EBB6-4642-B34F-B66F46152230}.Release|x64.Build.0 = Release|x64

+		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}.Debug|x64.ActiveCfg = Debug|x64

 		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}.Debug|x64.Build.0 = Debug|x64

+		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}.Release|Any CPU.ActiveCfg = Release|x64

 		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}.Release|x64.ActiveCfg = Release|x64

 		{448A0D5F-A8DE-4CAA-8224-0A9A63A9392E}.Release|x64.Build.0 = Release|x64

+		{FE4CEA75-2F26-4C97-B256-375AA698B4A9}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{FE4CEA75-2F26-4C97-B256-375AA698B4A9}.Debug|x64.ActiveCfg = Debug|x64

 		{FE4CEA75-2F26-4C97-B256-375AA698B4A9}.Debug|x64.Build.0 = Debug|x64

+		{FE4CEA75-2F26-4C97-B256-375AA698B4A9}.Release|Any CPU.ActiveCfg = Release|x64

 		{FE4CEA75-2F26-4C97-B256-375AA698B4A9}.Release|x64.ActiveCfg = Release|x64

 		{FE4CEA75-2F26-4C97-B256-375AA698B4A9}.Release|x64.Build.0 = Release|x64

+		{16E1218C-9A3C-49E2-A939-C29944BBB72E}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{16E1218C-9A3C-49E2-A939-C29944BBB72E}.Debug|x64.ActiveCfg = Debug|x64

 		{16E1218C-9A3C-49E2-A939-C29944BBB72E}.Debug|x64.Build.0 = Debug|x64

+		{16E1218C-9A3C-49E2-A939-C29944BBB72E}.Release|Any CPU.ActiveCfg = Release|x64

 		{16E1218C-9A3C-49E2-A939-C29944BBB72E}.Release|x64.ActiveCfg = Release|x64

 		{16E1218C-9A3C-49E2-A939-C29944BBB72E}.Release|x64.Build.0 = Release|x64

+		{C7314C70-7D05-4A77-B442-712712C60E16}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{C7314C70-7D05-4A77-B442-712712C60E16}.Debug|x64.ActiveCfg = Debug|x64

 		{C7314C70-7D05-4A77-B442-712712C60E16}.Debug|x64.Build.0 = Debug|x64

+		{C7314C70-7D05-4A77-B442-712712C60E16}.Release|Any CPU.ActiveCfg = Release|x64

 		{C7314C70-7D05-4A77-B442-712712C60E16}.Release|x64.ActiveCfg = Release|x64

 		{C7314C70-7D05-4A77-B442-712712C60E16}.Release|x64.Build.0 = Release|x64

+		{1E2B189D-239E-419F-BA09-2A3B28EF98EB}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{1E2B189D-239E-419F-BA09-2A3B28EF98EB}.Debug|x64.ActiveCfg = Debug|x64

 		{1E2B189D-239E-419F-BA09-2A3B28EF98EB}.Debug|x64.Build.0 = Debug|x64

+		{1E2B189D-239E-419F-BA09-2A3B28EF98EB}.Release|Any CPU.ActiveCfg = Release|x64

 		{1E2B189D-239E-419F-BA09-2A3B28EF98EB}.Release|x64.ActiveCfg = Release|x64

 		{1E2B189D-239E-419F-BA09-2A3B28EF98EB}.Release|x64.Build.0 = Release|x64

+		{F92D4129-C094-458D-8DFE-B1454A62DA0F}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{F92D4129-C094-458D-8DFE-B1454A62DA0F}.Debug|x64.ActiveCfg = Debug|x64

 		{F92D4129-C094-458D-8DFE-B1454A62DA0F}.Debug|x64.Build.0 = Debug|x64

+		{F92D4129-C094-458D-8DFE-B1454A62DA0F}.Release|Any CPU.ActiveCfg = Release|x64

 		{F92D4129-C094-458D-8DFE-B1454A62DA0F}.Release|x64.ActiveCfg = Release|x64

 		{F92D4129-C094-458D-8DFE-B1454A62DA0F}.Release|x64.Build.0 = Release|x64

+		{4C617764-FD55-4915-BACA-29D88A6B7C55}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{4C617764-FD55-4915-BACA-29D88A6B7C55}.Debug|x64.ActiveCfg = Debug|x64

 		{4C617764-FD55-4915-BACA-29D88A6B7C55}.Debug|x64.Build.0 = Debug|x64

+		{4C617764-FD55-4915-BACA-29D88A6B7C55}.Release|Any CPU.ActiveCfg = Release|x64

 		{4C617764-FD55-4915-BACA-29D88A6B7C55}.Release|x64.ActiveCfg = Release|x64

 		{4C617764-FD55-4915-BACA-29D88A6B7C55}.Release|x64.Build.0 = Release|x64

+		{E1CB058B-DFAC-48CB-818E-4790D2C1701F}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{E1CB058B-DFAC-48CB-818E-4790D2C1701F}.Debug|x64.ActiveCfg = Debug|x64

 		{E1CB058B-DFAC-48CB-818E-4790D2C1701F}.Debug|x64.Build.0 = Debug|x64

+		{E1CB058B-DFAC-48CB-818E-4790D2C1701F}.Release|Any CPU.ActiveCfg = Release|x64

 		{E1CB058B-DFAC-48CB-818E-4790D2C1701F}.Release|x64.ActiveCfg = Release|x64

 		{E1CB058B-DFAC-48CB-818E-4790D2C1701F}.Release|x64.Build.0 = Release|x64

+		{8DF28709-0405-4EF9-A525-19D177032073}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{8DF28709-0405-4EF9-A525-19D177032073}.Debug|x64.ActiveCfg = Debug|x64

 		{8DF28709-0405-4EF9-A525-19D177032073}.Debug|x64.Build.0 = Debug|x64

+		{8DF28709-0405-4EF9-A525-19D177032073}.Release|Any CPU.ActiveCfg = Release|x64

 		{8DF28709-0405-4EF9-A525-19D177032073}.Release|x64.ActiveCfg = Release|x64

 		{8DF28709-0405-4EF9-A525-19D177032073}.Release|x64.Build.0 = Release|x64

+		{C61EDCD2-36AB-4F46-8886-40E6BDE05FAC}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{C61EDCD2-36AB-4F46-8886-40E6BDE05FAC}.Debug|x64.ActiveCfg = Debug|x64

 		{C61EDCD2-36AB-4F46-8886-40E6BDE05FAC}.Debug|x64.Build.0 = Debug|x64

+		{C61EDCD2-36AB-4F46-8886-40E6BDE05FAC}.Release|Any CPU.ActiveCfg = Release|x64

 		{C61EDCD2-36AB-4F46-8886-40E6BDE05FAC}.Release|x64.ActiveCfg = Release|x64

 		{C61EDCD2-36AB-4F46-8886-40E6BDE05FAC}.Release|x64.Build.0 = Release|x64

+		{421744DE-5FB7-4694-98A7-00E4248A8B8C}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{421744DE-5FB7-4694-98A7-00E4248A8B8C}.Debug|x64.ActiveCfg = Debug|x64

 		{421744DE-5FB7-4694-98A7-00E4248A8B8C}.Debug|x64.Build.0 = Debug|x64

+		{421744DE-5FB7-4694-98A7-00E4248A8B8C}.Release|Any CPU.ActiveCfg = Release|x64

 		{421744DE-5FB7-4694-98A7-00E4248A8B8C}.Release|x64.ActiveCfg = Release|x64

 		{421744DE-5FB7-4694-98A7-00E4248A8B8C}.Release|x64.Build.0 = Release|x64

+		{6AB95745-BE93-4BF0-B3D3-C99EAB716F6B}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{6AB95745-BE93-4BF0-B3D3-C99EAB716F6B}.Debug|x64.ActiveCfg = Debug|x64

 		{6AB95745-BE93-4BF0-B3D3-C99EAB716F6B}.Debug|x64.Build.0 = Debug|x64

+		{6AB95745-BE93-4BF0-B3D3-C99EAB716F6B}.Release|Any CPU.ActiveCfg = Release|x64

 		{6AB95745-BE93-4BF0-B3D3-C99EAB716F6B}.Release|x64.ActiveCfg = Release|x64

 		{6AB95745-BE93-4BF0-B3D3-C99EAB716F6B}.Release|x64.Build.0 = Release|x64

+		{558927C3-045B-405D-A978-9E89D50BB51A}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{558927C3-045B-405D-A978-9E89D50BB51A}.Debug|x64.ActiveCfg = Debug|x64

 		{558927C3-045B-405D-A978-9E89D50BB51A}.Debug|x64.Build.0 = Debug|x64

+		{558927C3-045B-405D-A978-9E89D50BB51A}.Release|Any CPU.ActiveCfg = Release|x64

 		{558927C3-045B-405D-A978-9E89D50BB51A}.Release|x64.ActiveCfg = Release|x64

 		{558927C3-045B-405D-A978-9E89D50BB51A}.Release|x64.Build.0 = Release|x64

+		{E68A8740-AEA1-423E-B32B-E873F787CF60}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{E68A8740-AEA1-423E-B32B-E873F787CF60}.Debug|x64.ActiveCfg = Debug|x64

 		{E68A8740-AEA1-423E-B32B-E873F787CF60}.Debug|x64.Build.0 = Debug|x64

+		{E68A8740-AEA1-423E-B32B-E873F787CF60}.Release|Any CPU.ActiveCfg = Release|x64

 		{E68A8740-AEA1-423E-B32B-E873F787CF60}.Release|x64.ActiveCfg = Release|x64

 		{E68A8740-AEA1-423E-B32B-E873F787CF60}.Release|x64.Build.0 = Release|x64

+		{2C11BA8F-9F2D-4A94-B9E1-6F7CC2F99A96}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{2C11BA8F-9F2D-4A94-B9E1-6F7CC2F99A96}.Debug|x64.ActiveCfg = Debug|x64

 		{2C11BA8F-9F2D-4A94-B9E1-6F7CC2F99A96}.Debug|x64.Build.0 = Debug|x64

+		{2C11BA8F-9F2D-4A94-B9E1-6F7CC2F99A96}.Release|Any CPU.ActiveCfg = Release|x64

 		{2C11BA8F-9F2D-4A94-B9E1-6F7CC2F99A96}.Release|x64.ActiveCfg = Release|x64

 		{2C11BA8F-9F2D-4A94-B9E1-6F7CC2F99A96}.Release|x64.Build.0 = Release|x64

+		{74A9ED6D-EE76-4DFF-A921-F6D761C2CB7A}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{74A9ED6D-EE76-4DFF-A921-F6D761C2CB7A}.Debug|x64.ActiveCfg = Debug|x64

 		{74A9ED6D-EE76-4DFF-A921-F6D761C2CB7A}.Debug|x64.Build.0 = Debug|x64

+		{74A9ED6D-EE76-4DFF-A921-F6D761C2CB7A}.Release|Any CPU.ActiveCfg = Release|x64

 		{74A9ED6D-EE76-4DFF-A921-F6D761C2CB7A}.Release|x64.ActiveCfg = Release|x64

 		{74A9ED6D-EE76-4DFF-A921-F6D761C2CB7A}.Release|x64.Build.0 = Release|x64

+		{4AFF480F-006F-4229-8565-DB8F0E5F0C1D}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{4AFF480F-006F-4229-8565-DB8F0E5F0C1D}.Debug|x64.ActiveCfg = Debug|x64

 		{4AFF480F-006F-4229-8565-DB8F0E5F0C1D}.Debug|x64.Build.0 = Debug|x64

+		{4AFF480F-006F-4229-8565-DB8F0E5F0C1D}.Release|Any CPU.ActiveCfg = Release|x64

 		{4AFF480F-006F-4229-8565-DB8F0E5F0C1D}.Release|x64.ActiveCfg = Release|x64

 		{4AFF480F-006F-4229-8565-DB8F0E5F0C1D}.Release|x64.Build.0 = Release|x64

+		{A23F679F-233A-41A1-9964-61A0576E5D93}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{A23F679F-233A-41A1-9964-61A0576E5D93}.Debug|x64.ActiveCfg = Debug|x64

 		{A23F679F-233A-41A1-9964-61A0576E5D93}.Debug|x64.Build.0 = Debug|x64

+		{A23F679F-233A-41A1-9964-61A0576E5D93}.Release|Any CPU.ActiveCfg = Release|x64

 		{A23F679F-233A-41A1-9964-61A0576E5D93}.Release|x64.ActiveCfg = Release|x64

 		{A23F679F-233A-41A1-9964-61A0576E5D93}.Release|x64.Build.0 = Release|x64

+		{C3F0F0F8-0001-44C3-998F-89992361FA43}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{C3F0F0F8-0001-44C3-998F-89992361FA43}.Debug|x64.ActiveCfg = Debug|x64

 		{C3F0F0F8-0001-44C3-998F-89992361FA43}.Debug|x64.Build.0 = Debug|x64

+		{C3F0F0F8-0001-44C3-998F-89992361FA43}.Release|Any CPU.ActiveCfg = Release|x64

 		{C3F0F0F8-0001-44C3-998F-89992361FA43}.Release|x64.ActiveCfg = Release|x64

 		{C3F0F0F8-0001-44C3-998F-89992361FA43}.Release|x64.Build.0 = Release|x64

+		{EB9E67A8-0D79-4355-8699-724FF8F40D39}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{EB9E67A8-0D79-4355-8699-724FF8F40D39}.Debug|x64.ActiveCfg = Debug|x64

 		{EB9E67A8-0D79-4355-8699-724FF8F40D39}.Debug|x64.Build.0 = Debug|x64

+		{EB9E67A8-0D79-4355-8699-724FF8F40D39}.Release|Any CPU.ActiveCfg = Release|x64

 		{EB9E67A8-0D79-4355-8699-724FF8F40D39}.Release|x64.ActiveCfg = Release|x64

 		{EB9E67A8-0D79-4355-8699-724FF8F40D39}.Release|x64.Build.0 = Release|x64

+		{D5E2987D-234B-4EAB-85FA-BB377FE63C42}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{D5E2987D-234B-4EAB-85FA-BB377FE63C42}.Debug|x64.ActiveCfg = Debug|x64

 		{D5E2987D-234B-4EAB-85FA-BB377FE63C42}.Debug|x64.Build.0 = Debug|x64

+		{D5E2987D-234B-4EAB-85FA-BB377FE63C42}.Release|Any CPU.ActiveCfg = Release|x64

 		{D5E2987D-234B-4EAB-85FA-BB377FE63C42}.Release|x64.ActiveCfg = Release|x64

 		{D5E2987D-234B-4EAB-85FA-BB377FE63C42}.Release|x64.Build.0 = Release|x64

+		{80036B79-DAF4-4EDD-854E-1ADCBEBEB803}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{80036B79-DAF4-4EDD-854E-1ADCBEBEB803}.Debug|x64.ActiveCfg = Debug|x64

 		{80036B79-DAF4-4EDD-854E-1ADCBEBEB803}.Debug|x64.Build.0 = Debug|x64

+		{80036B79-DAF4-4EDD-854E-1ADCBEBEB803}.Release|Any CPU.ActiveCfg = Release|x64

 		{80036B79-DAF4-4EDD-854E-1ADCBEBEB803}.Release|x64.ActiveCfg = Release|x64

 		{80036B79-DAF4-4EDD-854E-1ADCBEBEB803}.Release|x64.Build.0 = Release|x64

+		{880CF3D8-B8A8-4350-A067-50A589563848}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{880CF3D8-B8A8-4350-A067-50A589563848}.Debug|x64.ActiveCfg = Debug|x64

 		{880CF3D8-B8A8-4350-A067-50A589563848}.Debug|x64.Build.0 = Debug|x64

+		{880CF3D8-B8A8-4350-A067-50A589563848}.Release|Any CPU.ActiveCfg = Release|x64

 		{880CF3D8-B8A8-4350-A067-50A589563848}.Release|x64.ActiveCfg = Release|x64

 		{880CF3D8-B8A8-4350-A067-50A589563848}.Release|x64.Build.0 = Release|x64

+		{CF4985C6-A06B-4F20-B5C3-489889170DB7}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{CF4985C6-A06B-4F20-B5C3-489889170DB7}.Debug|x64.ActiveCfg = Debug|x64

 		{CF4985C6-A06B-4F20-B5C3-489889170DB7}.Debug|x64.Build.0 = Debug|x64

+		{CF4985C6-A06B-4F20-B5C3-489889170DB7}.Release|Any CPU.ActiveCfg = Release|x64

 		{CF4985C6-A06B-4F20-B5C3-489889170DB7}.Release|x64.ActiveCfg = Release|x64

 		{CF4985C6-A06B-4F20-B5C3-489889170DB7}.Release|x64.Build.0 = Release|x64

+		{F98C05F8-584B-4BA1-ABC1-74C04B03932D}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{F98C05F8-584B-4BA1-ABC1-74C04B03932D}.Debug|x64.ActiveCfg = Debug|x64

 		{F98C05F8-584B-4BA1-ABC1-74C04B03932D}.Debug|x64.Build.0 = Debug|x64

+		{F98C05F8-584B-4BA1-ABC1-74C04B03932D}.Release|Any CPU.ActiveCfg = Release|x64

 		{F98C05F8-584B-4BA1-ABC1-74C04B03932D}.Release|x64.ActiveCfg = Release|x64

 		{F98C05F8-584B-4BA1-ABC1-74C04B03932D}.Release|x64.Build.0 = Release|x64

+		{704D00D3-9B85-46E5-BA68-7DE9CC484AA8}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{704D00D3-9B85-46E5-BA68-7DE9CC484AA8}.Debug|x64.ActiveCfg = Debug|x64

 		{704D00D3-9B85-46E5-BA68-7DE9CC484AA8}.Debug|x64.Build.0 = Debug|x64

+		{704D00D3-9B85-46E5-BA68-7DE9CC484AA8}.Release|Any CPU.ActiveCfg = Release|x64

 		{704D00D3-9B85-46E5-BA68-7DE9CC484AA8}.Release|x64.ActiveCfg = Release|x64

 		{704D00D3-9B85-46E5-BA68-7DE9CC484AA8}.Release|x64.Build.0 = Release|x64

+		{8E4F8CA1-26FF-4877-8446-0312F1CBDB85}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{8E4F8CA1-26FF-4877-8446-0312F1CBDB85}.Debug|x64.ActiveCfg = Debug|x64

 		{8E4F8CA1-26FF-4877-8446-0312F1CBDB85}.Debug|x64.Build.0 = Debug|x64

+		{8E4F8CA1-26FF-4877-8446-0312F1CBDB85}.Release|Any CPU.ActiveCfg = Release|x64

 		{8E4F8CA1-26FF-4877-8446-0312F1CBDB85}.Release|x64.ActiveCfg = Release|x64

 		{8E4F8CA1-26FF-4877-8446-0312F1CBDB85}.Release|x64.Build.0 = Release|x64

+		{D9F9E9BA-DCFF-44CB-81E8-91E5FF5BADBA}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{D9F9E9BA-DCFF-44CB-81E8-91E5FF5BADBA}.Debug|x64.ActiveCfg = Debug|x64

 		{D9F9E9BA-DCFF-44CB-81E8-91E5FF5BADBA}.Debug|x64.Build.0 = Debug|x64

+		{D9F9E9BA-DCFF-44CB-81E8-91E5FF5BADBA}.Release|Any CPU.ActiveCfg = Release|x64

 		{D9F9E9BA-DCFF-44CB-81E8-91E5FF5BADBA}.Release|x64.ActiveCfg = Release|x64

 		{D9F9E9BA-DCFF-44CB-81E8-91E5FF5BADBA}.Release|x64.Build.0 = Release|x64

+		{C22416C6-AF4C-47C6-BBE1-EF23D981AA44}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{C22416C6-AF4C-47C6-BBE1-EF23D981AA44}.Debug|x64.ActiveCfg = Debug|x64

 		{C22416C6-AF4C-47C6-BBE1-EF23D981AA44}.Debug|x64.Build.0 = Debug|x64

+		{C22416C6-AF4C-47C6-BBE1-EF23D981AA44}.Release|Any CPU.ActiveCfg = Release|x64

 		{C22416C6-AF4C-47C6-BBE1-EF23D981AA44}.Release|x64.ActiveCfg = Release|x64

 		{C22416C6-AF4C-47C6-BBE1-EF23D981AA44}.Release|x64.Build.0 = Release|x64

+		{C80B4A96-BAAD-4526-921C-FB5DADBC135E}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{C80B4A96-BAAD-4526-921C-FB5DADBC135E}.Debug|x64.ActiveCfg = Debug|x64

 		{C80B4A96-BAAD-4526-921C-FB5DADBC135E}.Debug|x64.Build.0 = Debug|x64

+		{C80B4A96-BAAD-4526-921C-FB5DADBC135E}.Release|Any CPU.ActiveCfg = Release|x64

 		{C80B4A96-BAAD-4526-921C-FB5DADBC135E}.Release|x64.ActiveCfg = Release|x64

 		{C80B4A96-BAAD-4526-921C-FB5DADBC135E}.Release|x64.Build.0 = Release|x64

+		{F7D5EAB5-65F8-45B5-9318-60EC311E08C6}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{F7D5EAB5-65F8-45B5-9318-60EC311E08C6}.Debug|x64.ActiveCfg = Debug|x64

 		{F7D5EAB5-65F8-45B5-9318-60EC311E08C6}.Debug|x64.Build.0 = Debug|x64

+		{F7D5EAB5-65F8-45B5-9318-60EC311E08C6}.Release|Any CPU.ActiveCfg = Release|x64

 		{F7D5EAB5-65F8-45B5-9318-60EC311E08C6}.Release|x64.ActiveCfg = Release|x64

 		{F7D5EAB5-65F8-45B5-9318-60EC311E08C6}.Release|x64.Build.0 = Release|x64

+		{81575917-C673-4E6F-9CF1-0DD35FC5E717}.Debug|Any CPU.ActiveCfg = Debug|x64

 		{81575917-C673-4E6F-9CF1-0DD35FC5E717}.Debug|x64.ActiveCfg = Debug|x64

 		{81575917-C673-4E6F-9CF1-0DD35FC5E717}.Debug|x64.Build.0 = Debug|x64

+		{81575917-C673-4E6F-9CF1-0DD35FC5E717}.Release|Any CPU.ActiveCfg = Release|x64

 		{81575917-C673-4E6F-9CF1-0DD35FC5E717}.Release|x64.ActiveCfg = Release|x64

 		{81575917-C673-4E6F-9CF1-0DD35FC5E717}.Release|x64.Build.0 = Release|x64

+		{5961DBD3-9A65-4B9C-B9D2-7139954F3163}.Debug|Any CPU.ActiveCfg = Debug|x64

+		{5961DBD3-9A65-4B9C-B9D2-7139954F3163}.Debug|x64.ActiveCfg = Debug|x64

+		{5961DBD3-9A65-4B9C-B9D2-7139954F3163}.Debug|x64.Build.0 = Debug|x64

+		{5961DBD3-9A65-4B9C-B9D2-7139954F3163}.Release|Any CPU.ActiveCfg = Release|x64

+		{5961DBD3-9A65-4B9C-B9D2-7139954F3163}.Release|x64.ActiveCfg = Release|x64

+		{5961DBD3-9A65-4B9C-B9D2-7139954F3163}.Release|x64.Build.0 = Release|x64

+		{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}.Debug|Any CPU.ActiveCfg = Debug|x64

+		{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}.Debug|x64.ActiveCfg = Debug|x64

+		{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}.Debug|x64.Build.0 = Debug|x64

+		{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}.Release|Any CPU.ActiveCfg = Release|x64

+		{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}.Release|x64.ActiveCfg = Release|x64

+		{5A3AD8DA-D876-4EA5-A96D-16E099C87BE4}.Release|x64.Build.0 = Release|x64

+		{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}.Debug|Any CPU.ActiveCfg = Debug|x64

+		{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}.Debug|x64.ActiveCfg = Debug|x64

+		{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}.Debug|x64.Build.0 = Debug|x64

+		{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}.Release|Any CPU.ActiveCfg = Release|x64

+		{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}.Release|x64.ActiveCfg = Release|x64

+		{60F765D6-4BC9-45A0-8EED-ECEB5E56EDAD}.Release|x64.Build.0 = Release|x64

+		{848458F1-0E94-46A2-A35D-03F96286182A}.Debug|Any CPU.ActiveCfg = Debug|x64

+		{848458F1-0E94-46A2-A35D-03F96286182A}.Debug|x64.ActiveCfg = Debug|x64

+		{848458F1-0E94-46A2-A35D-03F96286182A}.Debug|x64.Build.0 = Debug|x64

+		{848458F1-0E94-46A2-A35D-03F96286182A}.Release|Any CPU.ActiveCfg = Release|x64

+		{848458F1-0E94-46A2-A35D-03F96286182A}.Release|x64.ActiveCfg = Release|x64

+		{848458F1-0E94-46A2-A35D-03F96286182A}.Release|x64.Build.0 = Release|x64

+		{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}.Debug|Any CPU.ActiveCfg = Debug|x64

+		{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}.Debug|x64.ActiveCfg = Debug|x64

+		{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}.Debug|x64.Build.0 = Debug|x64

+		{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}.Release|Any CPU.ActiveCfg = Release|x64

+		{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}.Release|x64.ActiveCfg = Release|x64

+		{F5A9F4B6-9CFE-46A2-96FE-1C926445D88B}.Release|x64.Build.0 = Release|x64

+		{CA34E32B-0028-484C-B71C-75FE38036F08}.Debug|Any CPU.ActiveCfg = Debug|x64

+		{CA34E32B-0028-484C-B71C-75FE38036F08}.Debug|x64.ActiveCfg = Debug|x64

+		{CA34E32B-0028-484C-B71C-75FE38036F08}.Debug|x64.Build.0 = Debug|x64

+		{CA34E32B-0028-484C-B71C-75FE38036F08}.Release|Any CPU.ActiveCfg = Release|x64

+		{CA34E32B-0028-484C-B71C-75FE38036F08}.Release|x64.ActiveCfg = Release|x64

+		{CA34E32B-0028-484C-B71C-75FE38036F08}.Release|x64.Build.0 = Release|x64

 	EndGlobalSection

 	GlobalSection(SolutionProperties) = preSolution

 		HideSolutionNode = FALSE

diff --git a/lang/cs/Org.Apache.REEF.sln.DotSettings b/lang/cs/Org.Apache.REEF.sln.DotSettings
index c937155..fa90e22 100644
--- a/lang/cs/Org.Apache.REEF.sln.DotSettings
+++ b/lang/cs/Org.Apache.REEF.sln.DotSettings
@@ -25,6 +25,7 @@
 	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
 	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
 	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
 	<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean>
 	<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
 	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
@@ -66,7 +67,12 @@
 	<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=E620000127BE8148A2B0723F7161D4AB/RelativePath/@EntryValue"></s:String>
 	<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileE620000127BE8148A2B0723F7161D4AB/@KeyIndexDefined">True</s:Boolean>
 	<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileE620000127BE8148A2B0723F7161D4AB/RelativePriority/@EntryValue">1</s:Double>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/TextControl/HighlightCurrentLine/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/lang/cs/pomversion.targets b/lang/cs/pomversion.targets
index 6a35e6c..cd32f4a 100644
--- a/lang/cs/pomversion.targets
+++ b/lang/cs/pomversion.targets
@@ -15,17 +15,17 @@
 specific language governing permissions and limitations
 under the License.
 -->
-<Project InitialTargets="ExtractPOMVersion" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project InitialTargets="PrintMessage" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <PackageReference Include="RoslynCodeTaskFactory" Version="2.0.7" />
+  </ItemGroup>
   <!--
        ########################################################################
          Extract the REEF Version from the POM file 
        ######################################################################## 
   -->
   <!--A Task that extracts the version from the pom in a given folder.-->
-  <UsingTask
-    TaskName="GetMavenProjectVersion"
-    TaskFactory="CodeTaskFactory"
-    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
+  <UsingTask TaskName="GetMavenProjectVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(RoslynCodeTaskFactory)" Condition=" '$(RoslynCodeTaskFactory)' != '' ">
     <ParameterGroup>
       <SnapshotNumber/>
       <ProjectFolder Required="true"/>
@@ -39,7 +39,7 @@
       <Using Namespace="System.IO"/>
       <Using Namespace="System.Linq"/>
       <Using Namespace="System.Xml.Linq"/>
-      <Code Type="Fragment" Language="cs">
+      <Code Type="Fragment" Language="C#">
         <![CDATA[
           Version = XDocument.Load(Path.Combine(ProjectFolder, "pom.xml")).Descendants()
             .Where(x => x.Name.ToString().Contains("version"))
@@ -50,10 +50,14 @@
       </Code>
     </Task>
   </UsingTask>
+  
+  <Target Name="PrintMessage">
+    <Message Text="Roslyn code task factory is $(RoslynCodeTaskFactory)" Importance="high"/>
+  </Target>
   <!--
     A Target that extract the REEF version from the pom and makes it available as REEF_Version
   -->
-  <Target Name="ExtractPOMVersion">
+  <Target Name="ExtractPOMVersion" BeforeTargets="Build">
     <Message Text="MSBuildProjectName is $(MSBuildProjectName)" />
     <Message Text="MSBuildProjectDirectory is $(MSBuildProjectDirectory)" />
     <Message Text="SnapshotNumber is $(SnapshotNumber)" />
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/DriverServiceLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/DriverServiceLauncher.java
deleted file mode 100644
index a974383..0000000
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/DriverServiceLauncher.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.reef.bridge.client;
-
-import com.google.protobuf.util.JsonFormat;
-import org.apache.commons.lang.StringUtils;
-import org.apache.reef.annotations.Unstable;
-import org.apache.reef.annotations.audience.ClientSide;
-import org.apache.reef.bridge.driver.launch.BridgeDriverLauncher;
-import org.apache.reef.bridge.driver.launch.azbatch.AzureBatchLauncher;
-import org.apache.reef.bridge.driver.launch.local.LocalLauncher;
-import org.apache.reef.bridge.driver.launch.yarn.YarnLauncher;
-import org.apache.reef.bridge.driver.service.DriverServiceConfigurationProvider;
-import org.apache.reef.bridge.driver.service.grpc.GRPCDriverServiceConfigurationProvider;
-import org.apache.reef.bridge.driver.client.JavaDriverClientLauncher;
-import org.apache.reef.bridge.proto.ClientProtocol;
-import org.apache.reef.client.LauncherStatus;
-import org.apache.reef.runtime.azbatch.AzureBatchClasspathProvider;
-import org.apache.reef.runtime.common.files.*;
-import org.apache.reef.runtime.common.launch.JavaLaunchCommandBuilder;
-import org.apache.reef.runtime.local.LocalClasspathProvider;
-import org.apache.reef.runtime.yarn.YarnClasspathProvider;
-import org.apache.reef.runtime.yarn.util.YarnConfigurationConstructor;
-import org.apache.reef.tang.Configuration;
-import org.apache.reef.tang.Injector;
-import org.apache.reef.tang.Tang;
-import org.apache.reef.tang.exceptions.InjectionException;
-import org.apache.reef.tang.formats.ConfigurationSerializer;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Driver Service Launcher - main class.
- */
-@ClientSide
-@Unstable
-public final class DriverServiceLauncher {
-
-  /**
-   * Standard Java logger.
-   */
-  private static final Logger LOG = Logger.getLogger(DriverServiceLauncher.class.getName());
-
-  private static final Tang TANG = Tang.Factory.getTang();
-
-  /**
-   * This class should not be instantiated.
-   */
-  private DriverServiceLauncher() {
-    throw new RuntimeException("Do not instantiate this class!");
-  }
-
-  /**
-   * Submit a new REEF driver service (job).
-   * @param driverClientConfigurationProto client configuration protocol buffer
-   * @param driverClientConfiguration driver configuration
-   * @return LauncherStatus
-   * @throws InjectionException
-   * @throws IOException
-   */
-  public static LauncherStatus submit(
-      final ClientProtocol.DriverClientConfiguration driverClientConfigurationProto,
-      final Configuration driverClientConfiguration)
-      throws InjectionException, IOException {
-    ClientProtocol.DriverClientConfiguration.Builder builder =
-        ClientProtocol.DriverClientConfiguration.newBuilder(driverClientConfigurationProto);
-    final File driverClientConfigurationFile = File.createTempFile("driverclient", ".conf");
-    try {
-      // Write driver client configuration to a file
-      final Injector driverClientInjector = TANG.newInjector(driverClientConfiguration);
-      final ConfigurationSerializer configurationSerializer =
-          driverClientInjector.getInstance(ConfigurationSerializer.class);
-      configurationSerializer.toFile(driverClientConfiguration, driverClientConfigurationFile);
-
-      // Resolve Runtime ClassPath Provider.
-      final Configuration runtimeClassPathProvider;
-      switch (driverClientConfigurationProto.getRuntimeCase()) {
-      case YARN_RUNTIME:
-        runtimeClassPathProvider = TANG.newConfigurationBuilder()
-            .bind(RuntimeClasspathProvider.class, YarnClasspathProvider.class)
-            .bindConstructor(org.apache.hadoop.yarn.conf.YarnConfiguration.class,
-                YarnConfigurationConstructor.class)
-            .build();
-        break;
-      case LOCAL_RUNTIME:
-        runtimeClassPathProvider = TANG.newConfigurationBuilder()
-            .bind(RuntimeClasspathProvider.class, LocalClasspathProvider.class)
-            .build();
-        break;
-      case AZBATCH_RUNTIME:
-        runtimeClassPathProvider = TANG.newConfigurationBuilder()
-            .bind(RuntimeClasspathProvider.class, AzureBatchClasspathProvider.class)
-            .build();
-        break;
-      default:
-        throw new RuntimeException("unknown runtime " + driverClientConfigurationProto.getRuntimeCase());
-      }
-      final Injector runtimeInjector = TANG.newInjector(runtimeClassPathProvider);
-      final REEFFileNames fileNames = runtimeInjector.getInstance(REEFFileNames.class);
-      final ClasspathProvider classpathProvider = runtimeInjector.getInstance(ClasspathProvider.class);
-      final List<String> launchCommand = new JavaLaunchCommandBuilder(JavaDriverClientLauncher.class, null)
-          .setConfigurationFilePaths(
-              Collections.singletonList("./" + fileNames.getLocalFolderPath() + "/" +
-                  driverClientConfigurationFile.getName()))
-          .setJavaPath("java")
-          .setClassPath(driverClientConfigurationProto.getOperatingSystem() ==
-              ClientProtocol.DriverClientConfiguration.OS.WINDOWS ?
-              StringUtils.join(classpathProvider.getDriverClasspath(), ";") :
-              StringUtils.join(classpathProvider.getDriverClasspath(), ":"))
-          .build();
-      final String cmd = StringUtils.join(launchCommand, ' ');
-      builder.setDriverClientLaunchCommand(cmd);
-      builder.addLocalFiles(driverClientConfigurationFile.getAbsolutePath());
-
-      return launch(driverClientConfigurationProto);
-    } finally {
-      driverClientConfigurationFile.deleteOnExit();
-    }
-  }
-
-  private static LauncherStatus launch(
-      final ClientProtocol.DriverClientConfiguration driverClientConfigurationProto) throws InjectionException {
-
-    final ClientProtocol.DriverClientConfiguration.RuntimeCase runtime =
-        driverClientConfigurationProto.getRuntimeCase();
-
-    final Class<? extends BridgeDriverLauncher> launcherClass;
-    switch (runtime) {
-    case YARN_RUNTIME:
-      launcherClass = YarnLauncher.class;
-      break;
-    case LOCAL_RUNTIME:
-      launcherClass = LocalLauncher.class;
-      break;
-    case AZBATCH_RUNTIME:
-      launcherClass = AzureBatchLauncher.class;
-      break;
-    default:
-      throw new RuntimeException("Unknown runtime: " + runtime);
-    }
-    final Configuration jobSubmissionClientConfig = TANG.newConfigurationBuilder()
-        .bindImplementation(BridgeDriverLauncher.class, launcherClass)
-        .bindImplementation(DriverServiceConfigurationProvider.class,
-            GRPCDriverServiceConfigurationProvider.class)
-        .build();
-    final BridgeDriverLauncher driverServiceLauncher =
-        TANG.newInjector(jobSubmissionClientConfig).getInstance(launcherClass);
-    return driverServiceLauncher.launch(driverClientConfigurationProto);
-  }
-
-  /**
-   * Main method that launches the REEF job.
-   *
-   * @param args command line parameters.
-   */
-  public static void main(final String[] args) throws IOException, InjectionException {
-    if (args.length != 1) {
-      LOG.log(Level.SEVERE,
-          "Expected a single command line argument with a file containing client protobuf driver configuration");
-      System.exit(1);
-    }
-    final ClientProtocol.DriverClientConfiguration.Builder driverClientConfigurationProtoBuilder =
-        ClientProtocol.DriverClientConfiguration.newBuilder();
-    try (final Reader reader = new FileReader(args[0])) {
-      JsonFormat.parser()
-          .usingTypeRegistry(JsonFormat.TypeRegistry.getEmptyTypeRegistry())
-          .merge(reader, driverClientConfigurationProtoBuilder);
-    }
-    final ClientProtocol.DriverClientConfiguration driverClientConfigurationProto =
-        driverClientConfigurationProtoBuilder.build();
-    final LauncherStatus status = launch(driverClientConfigurationProto);
-    LOG.log(Level.INFO, "Status: {0}", status);
-  }
-}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientLauncher.java
new file mode 100644
index 0000000..e8d7931
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientLauncher.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.bridge.client.grpc;
+
+import com.google.protobuf.util.JsonFormat;
+import org.apache.reef.bridge.driver.launch.RuntimeConfigurationProvider;
+import org.apache.reef.bridge.driver.launch.azbatch.AzureBatchConfigurationProvider;
+import org.apache.reef.bridge.driver.launch.hdinsight.HDInsightConfigurationProvider;
+import org.apache.reef.bridge.driver.launch.local.LocalConfigurationProvider;
+import org.apache.reef.bridge.driver.launch.yarn.YarnConfigurationProvider;
+import org.apache.reef.bridge.driver.service.DriverServiceConfigurationProvider;
+import org.apache.reef.bridge.driver.service.grpc.GRPCDriverServiceConfigurationProvider;
+import org.apache.reef.bridge.proto.ClientProtocol;
+import org.apache.reef.client.ClientConfiguration;
+import org.apache.reef.client.LauncherStatus;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.Configurations;
+import org.apache.reef.tang.Tang;
+import org.apache.reef.tang.exceptions.InjectionException;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Client launcher.
+ */
+public final class ClientLauncher {
+  /**
+   * Standard Java logger.
+   */
+  private static final Logger LOG = Logger.getLogger(ClientLauncher.class.getName());
+
+  private static final Tang TANG = Tang.Factory.getTang();
+
+  private final RuntimeConfigurationProvider runtimeConfigurationProvider;
+
+  private final DriverServiceConfigurationProvider driverServiceConfigurationProvider;
+
+  /**
+   * This class should not be instantiated.
+   */
+  @Inject
+  private ClientLauncher(
+      final RuntimeConfigurationProvider runtimeConfigurationProvider,
+      final DriverServiceConfigurationProvider driverServiceConfigurationProvider) {
+    this.runtimeConfigurationProvider = runtimeConfigurationProvider;
+    this.driverServiceConfigurationProvider = driverServiceConfigurationProvider;
+  }
+
+  private LauncherStatus launch(final int port,
+      final ClientProtocol.DriverClientConfiguration driverClientConfigurationProto) {
+    try {
+      final Configuration runtimeConfiguration = Configurations.merge(
+          getClientServiceConfiguration(port),
+          this.runtimeConfigurationProvider.getRuntimeConfiguration(driverClientConfigurationProto));
+      try (ClientService clientService = TANG.newInjector(runtimeConfiguration).getInstance(ClientService.class)) {
+        return clientService.submit(
+            this.driverServiceConfigurationProvider.getDriverServiceConfiguration(driverClientConfigurationProto));
+      }
+    } catch (final InjectionException ex) {
+      LOG.log(Level.SEVERE, "Job configuration error", ex);
+      throw new RuntimeException("Could not launch driver service", ex);
+    }
+  }
+
+  static LauncherStatus submit(final int port,
+      final ClientProtocol.DriverClientConfiguration driverClientConfiguration)
+      throws InjectionException {
+    final Configuration driverServiceLauncherConfiguration;
+    switch (driverClientConfiguration.getRuntimeCase()) {
+    case YARN_RUNTIME:
+      driverServiceLauncherConfiguration = TANG.newConfigurationBuilder()
+          .bindImplementation(DriverServiceConfigurationProvider.class,
+              GRPCDriverServiceConfigurationProvider.class)
+          .bind(RuntimeConfigurationProvider.class, YarnConfigurationProvider.class)
+          .build();
+      break;
+    case LOCAL_RUNTIME:
+      driverServiceLauncherConfiguration = TANG.newConfigurationBuilder()
+          .bind(RuntimeConfigurationProvider.class, LocalConfigurationProvider.class)
+          .bindImplementation(DriverServiceConfigurationProvider.class,
+              GRPCDriverServiceConfigurationProvider.class)
+          .build();
+      break;
+    case AZBATCH_RUNTIME:
+      driverServiceLauncherConfiguration = TANG.newConfigurationBuilder()
+          .bind(RuntimeConfigurationProvider.class, AzureBatchConfigurationProvider.class)
+          .bindImplementation(DriverServiceConfigurationProvider.class,
+              GRPCDriverServiceConfigurationProvider.class)
+          .build();
+      break;
+    case HDI_RUNTIME:
+      driverServiceLauncherConfiguration = TANG.newConfigurationBuilder()
+          .bind(RuntimeConfigurationProvider.class, HDInsightConfigurationProvider.class)
+          .bindImplementation(DriverServiceConfigurationProvider.class,
+              GRPCDriverServiceConfigurationProvider.class)
+          .build();
+      break;
+    default:
+      throw new RuntimeException("unknown runtime " + driverClientConfiguration.getRuntimeCase());
+    }
+    return TANG.newInjector(driverServiceLauncherConfiguration).getInstance(ClientLauncher.class)
+        .launch(port, driverClientConfiguration);
+  }
+
+  private static Configuration getClientServiceConfiguration(final int port) {
+    return ClientServiceConfiguration.CONF
+        .set(ClientServiceConfiguration.CLIENT_SERVER_PORT, port)
+        .set(ClientConfiguration.ON_JOB_SUBMITTED, ClientService.SubmittedJobHandler.class)
+        .set(ClientConfiguration.ON_JOB_RUNNING, ClientService.RunningJobHandler.class)
+        .set(ClientConfiguration.ON_JOB_COMPLETED, ClientService.CompletedJobHandler.class)
+        .set(ClientConfiguration.ON_JOB_FAILED, ClientService.FailedJobHandler.class)
+        .set(ClientConfiguration.ON_JOB_MESSAGE, ClientService.JobMessageHandler.class)
+        .set(ClientConfiguration.ON_RUNTIME_ERROR, ClientService.RuntimeErrorHandler.class)
+        .set(ClientConfiguration.ON_WAKE_ERROR, ClientService.WakeErrorHandler.class)
+        .build();
+  }
+
+  /**
+   * Main method that launches the REEF job.
+   *
+   * @param args command line parameters.
+   */
+  public static void main(final String[] args) throws IOException, InjectionException {
+    final ClientProtocol.DriverClientConfiguration driverClientConfigurationProto;
+    if (args.length > 0) {
+      final String content = new String(Files.readAllBytes(Paths.get(args[0])));
+      final ClientProtocol.DriverClientConfiguration.Builder driverClientConfigurationProtoBuilder =
+          ClientProtocol.DriverClientConfiguration.newBuilder();
+      JsonFormat.parser()
+          .usingTypeRegistry(JsonFormat.TypeRegistry.getEmptyTypeRegistry())
+          .merge(content, driverClientConfigurationProtoBuilder);
+      driverClientConfigurationProto = driverClientConfigurationProtoBuilder.build();
+      final int port = (args.length == 2) ? Integer.parseInt(args[1]) : 0;
+      final LauncherStatus status = submit(port, driverClientConfigurationProto);
+      LOG.log(Level.INFO, "Status: {0}", status);
+    } else {
+      LOG.log(Level.SEVERE, ClientLauncher.class.getName() +
+          " accepts single required argument referencing a file that contains a " +
+          "client protocol buffer driver configuration");
+      System.exit(1);
+    }
+  }
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientService.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientService.java
new file mode 100644
index 0000000..b5b3d17
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientService.java
@@ -0,0 +1,323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.bridge.client.grpc;
+
+import com.google.protobuf.ByteString;
+import io.grpc.*;
+import io.grpc.stub.StreamObserver;
+import org.apache.reef.annotations.audience.ClientSide;
+import org.apache.reef.bridge.client.grpc.parameters.ClientServerPort;
+import org.apache.reef.bridge.proto.*;
+import org.apache.reef.bridge.proto.Void;
+import org.apache.reef.client.*;
+import org.apache.reef.exception.NonSerializableException;
+import org.apache.reef.runtime.common.utils.ExceptionCodec;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.InjectionFuture;
+import org.apache.reef.tang.annotations.Parameter;
+import org.apache.reef.tang.annotations.Unit;
+import org.apache.reef.util.Optional;
+import org.apache.reef.wake.EventHandler;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Client service.
+ */
+@ClientSide
+@Unit
+final class ClientService extends REEFClientGrpc.REEFClientImplBase implements AutoCloseable {
+
+  private static final Logger LOG = Logger.getLogger(ClientService.class.getName());
+
+  private final Object waitLock = new Object();
+
+  private final InjectionFuture<REEF> reef;
+
+  private final ExceptionCodec exceptionCodec;
+
+  private Server server = null;
+
+  private BridgeClientGrpc.BridgeClientFutureStub clientStub = null;
+
+  private LauncherStatus status = LauncherStatus.INIT;
+
+  private RunningJob theJob = null;
+
+  /**
+   * This class should not be instantiated.
+   */
+  @Inject
+  private ClientService(
+      @Parameter(ClientServerPort.class) final int clientServerPort,
+      final ExceptionCodec exceptionCodec,
+      final InjectionFuture<REEF> reef) {
+    this.reef = reef;
+    this.exceptionCodec = exceptionCodec;
+    if (clientServerPort > 0) {
+      try {
+        this.server =  ServerBuilder.forPort(0)
+            .addService(this)
+            .build()
+            .start();
+        final ManagedChannel channel = ManagedChannelBuilder
+            .forAddress("localhost", clientServerPort)
+            .usePlaintext()
+            .build();
+        this.clientStub = BridgeClientGrpc.newFutureStub(channel);
+        this.clientStub.registerREEFClient(
+            ClientProtocol.REEFClientRegistration.newBuilder()
+                .setHostname("localhost")
+                .setPort(this.server.getPort())
+                .build());
+      } catch (IOException e) {
+        throw new RuntimeException("unable to start gRPC server", e);
+      }
+    }
+  }
+
+  @Override
+  public void close() {
+    this.reef.get().close();
+    if (this.server != null) {
+      this.server.shutdown();
+      this.server = null;
+    }
+  }
+
+  public LauncherStatus submit(final Configuration driverServiceConfiguration) {
+    this.reef.get().submit(driverServiceConfiguration);
+    synchronized (this.waitLock) {
+      while (!this.status.isDone()) {
+        try {
+          LOG.log(Level.FINE, "Wait indefinitely");
+          this.waitLock.wait();
+        } catch (final InterruptedException ex) {
+          LOG.log(Level.FINE, "Interrupted: {0}", ex);
+        }
+      }
+    }
+    return this.status;
+  }
+
+  @Override
+  public void driverControlHandler(
+      final ClientProtocol.DriverControlOp request,
+      final StreamObserver<Void> responseObserver) {
+    try {
+      if (this.theJob != null && this.theJob.getId().equals(request.getJobId())) {
+        try {
+          switch (request.getOperation()) {
+          case CLOSE:
+            if (request.getMessage().isEmpty()) {
+              this.theJob.close();
+            } else {
+              this.theJob.close(request.getMessage().toByteArray());
+            }
+            break;
+          case MESSAGE:
+            this.theJob.send(request.getMessage().toByteArray());
+            break;
+          default:
+            throw new RuntimeException("Unknown operation " + request.getOperation());
+          }
+        } catch (Exception e) {
+          responseObserver.onError(Status.INTERNAL
+              .withDescription(e.getMessage())
+              .asRuntimeException());
+        } finally {
+          responseObserver.onNext(Void.newBuilder().build());
+        }
+      } else {
+        responseObserver.onError(Status.INTERNAL
+            .withDescription("Unknown job " + request.getJobId())
+            .asRuntimeException());
+      }
+    } finally {
+      responseObserver.onCompleted();
+    }
+  }
+
+  private void setStatusAndNotify(final LauncherStatus launcherStatus) {
+    synchronized (this.waitLock) {
+      this.status = launcherStatus;
+      this.waitLock.notify();
+    }
+  }
+
+  private ByteString getRootCause(final Throwable cause) {
+    Throwable t = cause;
+    LOG.log(Level.INFO, "Exception class {0}", t.getClass().getName());
+    while (t.getCause() != null) {
+      t = t.getCause();
+    }
+    // Do we bottom out at a non-serializable (e.g., C#) exception?
+    if (t instanceof NonSerializableException) {
+      LOG.log(Level.INFO, "non serializable exception");
+      return ByteString.copyFrom(((NonSerializableException)t).getError());
+    } else {
+      LOG.log(Level.INFO, "serializable exception found");
+      return ByteString.copyFrom(exceptionCodec.toBytes(t));
+    }
+  }
+
+  /**
+   * Job message handler.
+   */
+  final class JobMessageHandler implements EventHandler<JobMessage> {
+    @Override
+    public void onNext(final JobMessage value) {
+      LOG.log(Level.INFO, "Job message from id {0}", value.getId());
+      if (clientStub != null) {
+        clientStub.jobMessageHandler(ClientProtocol.JobMessageEvent.newBuilder()
+            .setJobId(value.getId())
+            .setMessage(ByteString.copyFrom(value.get()))
+            .build());
+      }
+    }
+  }
+
+  /**
+   * Job driver notifies us that the job has been submitted to the Resource Manager.
+   */
+  final class SubmittedJobHandler implements EventHandler<SubmittedJob> {
+    @Override
+    public void onNext(final SubmittedJob job) {
+      LOG.log(Level.INFO, "REEF job submitted: {0}.", job.getId());
+      setStatusAndNotify(LauncherStatus.SUBMITTED);
+      if (clientStub != null) {
+        clientStub.jobSumittedHandler(ClientProtocol.JobSubmittedEvent.newBuilder()
+            .setJobId(job.getId())
+            .build());
+      }
+    }
+  }
+
+  /**
+   * Job driver notifies us that the job is running.
+   */
+  final class RunningJobHandler implements EventHandler<RunningJob> {
+    @Override
+    public void onNext(final RunningJob job) {
+      LOG.log(Level.INFO, "The Job {0} is running.", job.getId());
+      theJob = job;
+      setStatusAndNotify(LauncherStatus.RUNNING);
+      if (clientStub != null) {
+        clientStub.jobRunningHandler(ClientProtocol.JobRunningEvent.newBuilder()
+            .setJobId(job.getId())
+            .build());
+      }
+    }
+  }
+
+  /**
+   * Job driver notifies us that the job had failed.
+   */
+  final class FailedJobHandler implements EventHandler<FailedJob> {
+    @Override
+    public void onNext(final FailedJob job) {
+      final Optional<Throwable> ex = job.getReason();
+      LOG.log(Level.SEVERE, "Received an error for job " + job.getId(), ex);
+      theJob = null;
+      setStatusAndNotify(LauncherStatus.failed(ex));
+      if (clientStub != null) {
+        final Optional<Throwable> error = exceptionCodec.fromBytes(job.getData().get());
+        final ExceptionInfo exception;
+        if (error.isPresent()) {
+          LOG.log(Level.SEVERE, "Error for " + job.getId(), ex);
+          exception = ExceptionInfo.newBuilder()
+              .setName(job.toString())
+              .setMessage(job.getMessage())
+              .setData(getRootCause(error.get()))
+              .build();
+        } else {
+          LOG.log(Level.SEVERE, "Unserialized error for job {0}: {1}",
+              new Object[] {job.getId(), job.getMessage()});
+          exception = ExceptionInfo.newBuilder()
+              .setName(job.toString())
+              .setMessage(job.getMessage())
+              .build();
+        }
+        clientStub.jobFailedHandler(ClientProtocol.JobFailedEvent.newBuilder()
+            .setJobId(job.getId())
+            .setException(exception)
+            .build());
+      }
+    }
+  }
+
+  /**
+   * Job driver notifies us that the job had completed successfully.
+   */
+  final class CompletedJobHandler implements EventHandler<CompletedJob> {
+    @Override
+    public void onNext(final CompletedJob job) {
+      LOG.log(Level.INFO, "The Job {0} is done.", job.getId());
+      theJob = null;
+      setStatusAndNotify(LauncherStatus.COMPLETED);
+      if (clientStub != null) {
+        clientStub.jobCompletedHandler(ClientProtocol.JobCompletedEvent.newBuilder()
+            .setJobId(job.getId())
+            .build());
+      }
+    }
+  }
+
+  /**
+   * Handler an error in the job driver.
+   */
+  final class RuntimeErrorHandler implements EventHandler<FailedRuntime> {
+    @Override
+    public void onNext(final FailedRuntime error) {
+      LOG.log(Level.SEVERE, "Received a resource manager error", error.getReason());
+      theJob = null;
+      setStatusAndNotify(LauncherStatus.failed(error.getReason()));
+      if (clientStub != null) {
+        clientStub.runtimeErrorHandler(ExceptionInfo.newBuilder()
+            .setMessage(error.getMessage())
+            .setName(error.getId())
+            .setData(error.getReason().isPresent() ?
+                getRootCause(error.getReason().get()) : ByteString.EMPTY)
+            .build());
+      }
+    }
+  }
+
+  /**
+   * Wake error handler.
+   */
+  final class WakeErrorHandler implements EventHandler<Throwable> {
+    @Override
+    public void onNext(final Throwable value) {
+      LOG.log(Level.SEVERE, "Received a wake error", value);
+      if (clientStub != null) {
+        clientStub.wakeErrorHandler(ExceptionInfo.newBuilder()
+            .setName(value.toString())
+            .setMessage(value.getMessage())
+            .setData(getRootCause(value))
+            .build());
+      }
+
+    }
+  }
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientServiceConfiguration.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientServiceConfiguration.java
new file mode 100644
index 0000000..f7bfd35
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/ClientServiceConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.bridge.client.grpc;
+
+import org.apache.reef.bridge.client.grpc.parameters.ClientServerPort;
+import org.apache.reef.client.ClientConfiguration;
+import org.apache.reef.tang.formats.ConfigurationModule;
+import org.apache.reef.tang.formats.ConfigurationModuleBuilder;
+import org.apache.reef.tang.formats.RequiredParameter;
+
+/**
+ * Client service configuration.
+ */
+public class ClientServiceConfiguration extends ConfigurationModuleBuilder {
+
+  public static final RequiredParameter<Integer> CLIENT_SERVER_PORT = new RequiredParameter<>();
+
+  static final ConfigurationModule CONF = new ClientServiceConfiguration()
+      .merge(ClientConfiguration.CONF)
+      .bindNamedParameter(ClientServerPort.class, CLIENT_SERVER_PORT)
+      .build();
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/JavaClientLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/JavaClientLauncher.java
new file mode 100644
index 0000000..5d535d9
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/JavaClientLauncher.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.bridge.client.grpc;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.reef.bridge.driver.client.JavaDriverClientLauncher;
+import org.apache.reef.bridge.proto.ClientProtocol;
+import org.apache.reef.client.LauncherStatus;
+import org.apache.reef.runtime.azbatch.AzureBatchClasspathProvider;
+import org.apache.reef.runtime.common.files.ClasspathProvider;
+import org.apache.reef.runtime.common.files.REEFFileNames;
+import org.apache.reef.runtime.common.files.RuntimeClasspathProvider;
+import org.apache.reef.runtime.common.launch.JavaLaunchCommandBuilder;
+import org.apache.reef.runtime.local.LocalClasspathProvider;
+import org.apache.reef.runtime.yarn.YarnClasspathProvider;
+import org.apache.reef.runtime.yarn.util.YarnConfigurationConstructor;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.Injector;
+import org.apache.reef.tang.Tang;
+import org.apache.reef.tang.exceptions.InjectionException;
+import org.apache.reef.tang.formats.ConfigurationSerializer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Java client launcher.
+ */
+public final class JavaClientLauncher {
+
+  private static final Tang TANG = Tang.Factory.getTang();
+
+  private JavaClientLauncher() {
+  }
+
+  /**
+   * Submit a new REEF driver service (job).
+   * @param driverClientConfigurationProto client configuration protocol buffer
+   * @param driverClientConfiguration driver configuration
+   * @return LauncherStatus
+   * @throws InjectionException
+   * @throws IOException
+   */
+  public static LauncherStatus submit(
+      final ClientProtocol.DriverClientConfiguration driverClientConfigurationProto,
+      final Configuration driverClientConfiguration)
+      throws InjectionException, IOException {
+    ClientProtocol.DriverClientConfiguration.Builder builder =
+        ClientProtocol.DriverClientConfiguration.newBuilder(driverClientConfigurationProto);
+    final File driverClientConfigurationFile = File.createTempFile("driverclient", ".conf");
+    try {
+      // Write driver client configuration to a file
+      final Injector driverClientInjector = TANG.newInjector(driverClientConfiguration);
+      final ConfigurationSerializer configurationSerializer =
+          driverClientInjector.getInstance(ConfigurationSerializer.class);
+      configurationSerializer.toFile(driverClientConfiguration, driverClientConfigurationFile);
+
+      // Resolve Runtime ClassPath Provider.
+      final Configuration runtimeClassPathProvider;
+      switch (driverClientConfigurationProto.getRuntimeCase()) {
+      case YARN_RUNTIME:
+        runtimeClassPathProvider = TANG.newConfigurationBuilder()
+            .bind(RuntimeClasspathProvider.class, YarnClasspathProvider.class)
+            .bindConstructor(org.apache.hadoop.yarn.conf.YarnConfiguration.class,
+                YarnConfigurationConstructor.class)
+            .build();
+        break;
+      case LOCAL_RUNTIME:
+        runtimeClassPathProvider = TANG.newConfigurationBuilder()
+            .bind(RuntimeClasspathProvider.class, LocalClasspathProvider.class)
+            .build();
+        break;
+      case AZBATCH_RUNTIME:
+        runtimeClassPathProvider = TANG.newConfigurationBuilder()
+            .bind(RuntimeClasspathProvider.class, AzureBatchClasspathProvider.class)
+            .build();
+        break;
+      default:
+        throw new RuntimeException("unknown runtime " + driverClientConfigurationProto.getRuntimeCase());
+      }
+      final Injector runtimeInjector = TANG.newInjector(runtimeClassPathProvider);
+      final REEFFileNames fileNames = runtimeInjector.getInstance(REEFFileNames.class);
+      final ClasspathProvider classpathProvider = runtimeInjector.getInstance(ClasspathProvider.class);
+      final List<String> launchCommand = new JavaLaunchCommandBuilder(JavaDriverClientLauncher.class, null)
+          .setConfigurationFilePaths(
+              Collections.singletonList("./" + fileNames.getLocalFolderPath() + "/" +
+                  driverClientConfigurationFile.getName()))
+          .setJavaPath("java")
+          .setClassPath(driverClientConfigurationProto.getOperatingSystem() ==
+              ClientProtocol.DriverClientConfiguration.OS.WINDOWS ?
+              StringUtils.join(classpathProvider.getDriverClasspath(), ";") :
+              StringUtils.join(classpathProvider.getDriverClasspath(), ":"))
+          .build();
+      final String cmd = StringUtils.join(launchCommand, ' ');
+      builder.setDriverClientLaunchCommand(cmd);
+      builder.addLocalFiles(driverClientConfigurationFile.getAbsolutePath());
+
+      return ClientLauncher.submit(0, builder.build());
+    } finally {
+      driverClientConfigurationFile.deleteOnExit();
+    }
+  }
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/package-info.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/package-info.java
new file mode 100644
index 0000000..67234e7
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/**
+ * Java client gRPC service.
+ */
+package org.apache.reef.bridge.client.grpc;
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/parameters/ClientServerPort.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/parameters/ClientServerPort.java
new file mode 100644
index 0000000..30392db
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/parameters/ClientServerPort.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.bridge.client.grpc.parameters;
+
+import org.apache.reef.tang.annotations.Name;
+import org.apache.reef.tang.annotations.NamedParameter;
+
+/**
+ * Client server port.
+ */
+@NamedParameter(doc = "the gRPC client server port", default_value = "0")
+public final class ClientServerPort implements Name<Integer> {
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/parameters/package-info.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/parameters/package-info.java
new file mode 100644
index 0000000..8dedcf7
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/client/grpc/parameters/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/**
+ * Java client gRPC service parameters.
+ */
+package org.apache.reef.bridge.client.grpc.parameters;
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/client/DriverClientConfiguration.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/client/DriverClientConfiguration.java
index 4df8941..7fc3f98 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/client/DriverClientConfiguration.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/client/DriverClientConfiguration.java
@@ -170,7 +170,6 @@
       .bindImplementation(AlarmDispatchHandler.class, ALARM_DISPATCH_HANDLER)
       .bindImplementation(DriverClientService.class, DRIVER_CLIENT_SERVICE)
       .bindImplementation(DriverServiceClient.class, DRIVER_SERVICE_CLIENT)
-
       .bindNamedParameter(DriverClientDispatchThreadCount.class, CLIENT_DRIVER_DISPATCH_THREAD_COUNT)
 
       // Driver start/stop handlers
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/common/grpc/GRPCUtils.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/common/grpc/GRPCUtils.java
index 75c1887..699ea54 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/common/grpc/GRPCUtils.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/common/grpc/GRPCUtils.java
@@ -20,6 +20,7 @@
 package org.apache.reef.bridge.driver.common.grpc;
 
 import com.google.protobuf.ByteString;
+import org.apache.commons.lang.StringUtils;
 import org.apache.reef.annotations.audience.Private;
 import org.apache.reef.bridge.proto.ContextInfo;
 import org.apache.reef.bridge.proto.EvaluatorDescriptorInfo;
@@ -65,7 +66,7 @@
   public static ExceptionInfo createExceptionInfo(final ExceptionCodec exceptionCodec, final Throwable ex)  {
     return ExceptionInfo.newBuilder()
         .setName(ex.getCause() != null ? ex.getCause().toString() : ex.toString())
-        .setMessage(ex.getMessage() == null ? ex.toString() : ex.getMessage())
+        .setMessage(StringUtils.isNotEmpty(ex.getMessage()) ? ex.getMessage() : ex.toString())
         .setData(ByteString.copyFrom(exceptionCodec.toBytes(ex)))
         .build();
   }
@@ -84,7 +85,7 @@
         EvaluatorDescriptorInfo.NodeDescriptorInfo.newBuilder()
             .setHostName(descriptor.getNodeDescriptor().getName())
             .setId(descriptor.getNodeDescriptor().getId())
-            .setIpAddress(descriptor.getNodeDescriptor().getInetSocketAddress().getAddress().toString())
+            .setIpAddress(descriptor.getNodeDescriptor().getInetSocketAddress().getAddress().getHostAddress())
             .setPort(descriptor.getNodeDescriptor().getInetSocketAddress().getPort())
             .setRackName(descriptor.getNodeDescriptor().getRackDescriptor() == null ?
                 "" : descriptor.getNodeDescriptor().getRackDescriptor().getName())
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/BridgeDriverLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/RuntimeConfigurationProvider.java
similarity index 71%
rename from lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/BridgeDriverLauncher.java
rename to lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/RuntimeConfigurationProvider.java
index 92de91b..a19c91d 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/BridgeDriverLauncher.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/RuntimeConfigurationProvider.java
@@ -20,19 +20,17 @@
 
 import org.apache.reef.annotations.Unstable;
 import org.apache.reef.bridge.proto.ClientProtocol;
-import org.apache.reef.client.LauncherStatus;
-import org.apache.reef.tang.exceptions.InjectionException;
+import org.apache.reef.tang.Configuration;
 
 /**
- * All driver launchers implement this method.
+ * All driver runtime providers implement this method.
  */
 @Unstable
-public interface BridgeDriverLauncher {
+public interface RuntimeConfigurationProvider {
 
   /**
-   * Launch the driver with the dynamic {@link ClientProtocol.DriverClientConfiguration}.
+   * Generate driver runtime configuration with the dynamic {@link ClientProtocol.DriverClientConfiguration}.
    * @param driverClientConfiguration dynamic driver configuration parameters
    */
-  LauncherStatus launch(final ClientProtocol.DriverClientConfiguration driverClientConfiguration)
-      throws InjectionException;
+  Configuration getRuntimeConfiguration(final ClientProtocol.DriverClientConfiguration driverClientConfiguration);
 }
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/azbatch/AzureBatchLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/azbatch/AzureBatchConfigurationProvider.java
similarity index 69%
rename from lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/azbatch/AzureBatchLauncher.java
rename to lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/azbatch/AzureBatchConfigurationProvider.java
index 48593b7..b372a34 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/azbatch/AzureBatchLauncher.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/azbatch/AzureBatchConfigurationProvider.java
@@ -19,37 +19,27 @@
 package org.apache.reef.bridge.driver.launch.azbatch;
 
 import org.apache.reef.annotations.audience.Private;
-import org.apache.reef.bridge.driver.launch.BridgeDriverLauncher;
-import org.apache.reef.bridge.driver.service.DriverServiceConfigurationProvider;
+import org.apache.reef.bridge.driver.launch.RuntimeConfigurationProvider;
 import org.apache.reef.bridge.proto.ClientProtocol;
-import org.apache.reef.client.DriverLauncher;
-import org.apache.reef.client.LauncherStatus;
 import org.apache.reef.runtime.azbatch.client.AzureBatchRuntimeConfiguration;
 import org.apache.reef.runtime.azbatch.client.AzureBatchRuntimeConfigurationCreator;
 import org.apache.reef.tang.Configuration;
-import org.apache.reef.tang.exceptions.InjectionException;
 
 import javax.inject.Inject;
 
 /**
- * This is a bootstrap launcher for Azure Batch for submission from C#. It allows for Java Driver
- * configuration generation directly on the Driver without need of Java dependency if REST
- * submission is used.
+ * Azure batch runtime configuration provider.
  */
 @Private
-public final class AzureBatchLauncher implements BridgeDriverLauncher {
-
-  private final DriverServiceConfigurationProvider driverServiceConfigurationProvider;
+public final class AzureBatchConfigurationProvider implements RuntimeConfigurationProvider {
 
   @Inject
-  private AzureBatchLauncher(final DriverServiceConfigurationProvider driverServiceConfigurationProvider) {
-    this.driverServiceConfigurationProvider = driverServiceConfigurationProvider;
+  private AzureBatchConfigurationProvider() {
   }
 
-  public LauncherStatus launch(final ClientProtocol.DriverClientConfiguration driverClientConfiguration)
-      throws InjectionException {
-    return DriverLauncher.getLauncher(generateConfigurationFromJobSubmissionParameters(driverClientConfiguration))
-        .run(driverServiceConfigurationProvider.getDriverServiceConfiguration(driverClientConfiguration));
+  public Configuration getRuntimeConfiguration(
+      final ClientProtocol.DriverClientConfiguration driverClientConfiguration) {
+    return generateConfigurationFromJobSubmissionParameters(driverClientConfiguration);
   }
 
   private static Configuration generateConfigurationFromJobSubmissionParameters(
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/hdinsight/HDInsightConfigurationProvider.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/hdinsight/HDInsightConfigurationProvider.java
new file mode 100644
index 0000000..eb9d967
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/hdinsight/HDInsightConfigurationProvider.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.reef.bridge.driver.launch.hdinsight;
+
+import org.apache.reef.annotations.audience.Private;
+import org.apache.reef.bridge.driver.launch.RuntimeConfigurationProvider;
+import org.apache.reef.bridge.proto.ClientProtocol;
+import org.apache.reef.runtime.hdinsight.client.HDInsightRuntimeConfiguration;
+import org.apache.reef.runtime.hdinsight.client.UnsafeHDInsightRuntimeConfiguration;
+import org.apache.reef.tang.Configuration;
+
+import javax.inject.Inject;
+
+/**
+ * Azure batch runtime configuration provider.
+ */
+@Private
+public final class HDInsightConfigurationProvider implements RuntimeConfigurationProvider {
+
+  @Inject
+  private HDInsightConfigurationProvider() {
+  }
+
+  public Configuration getRuntimeConfiguration(
+      final ClientProtocol.DriverClientConfiguration driverClientConfiguration) {
+    return generateConfigurationFromJobSubmissionParameters(driverClientConfiguration);
+  }
+
+  private static Configuration generateConfigurationFromJobSubmissionParameters(
+      final ClientProtocol.DriverClientConfiguration driverClientConfiguration) {
+    if (driverClientConfiguration.getHdiRuntime().getUnsafe()) {
+      return UnsafeHDInsightRuntimeConfiguration.CONF
+          .set(UnsafeHDInsightRuntimeConfiguration.USER_NAME,
+              driverClientConfiguration.getHdiRuntime().getHdiUserName())
+          .set(UnsafeHDInsightRuntimeConfiguration.PASSWORD,
+              driverClientConfiguration.getHdiRuntime().getHdiPassword())
+          .set(UnsafeHDInsightRuntimeConfiguration.URL,
+              driverClientConfiguration.getHdiRuntime().getHdiUrl())
+          .set(UnsafeHDInsightRuntimeConfiguration.STORAGE_ACCOUNT_NAME,
+              driverClientConfiguration.getHdiRuntime().getAzureStorageAccountName())
+          .set(UnsafeHDInsightRuntimeConfiguration.STORAGE_ACCOUNT_KEY,
+              driverClientConfiguration.getHdiRuntime().getAzureStorageAccountKey())
+          .set(UnsafeHDInsightRuntimeConfiguration.CONTAINER_NAME,
+              driverClientConfiguration.getHdiRuntime().getAzureStorageContainerName())
+          .build();
+    } else {
+      return HDInsightRuntimeConfiguration.CONF
+          .set(HDInsightRuntimeConfiguration.USER_NAME,
+              driverClientConfiguration.getHdiRuntime().getHdiUserName())
+          .set(HDInsightRuntimeConfiguration.PASSWORD,
+              driverClientConfiguration.getHdiRuntime().getHdiPassword())
+          .set(HDInsightRuntimeConfiguration.URL,
+              driverClientConfiguration.getHdiRuntime().getHdiUrl())
+          .set(HDInsightRuntimeConfiguration.STORAGE_ACCOUNT_NAME,
+              driverClientConfiguration.getHdiRuntime().getAzureStorageAccountName())
+          .set(HDInsightRuntimeConfiguration.STORAGE_ACCOUNT_KEY,
+              driverClientConfiguration.getHdiRuntime().getAzureStorageAccountKey())
+          .set(HDInsightRuntimeConfiguration.CONTAINER_NAME,
+              driverClientConfiguration.getHdiRuntime().getAzureStorageContainerName())
+          .build();
+    }
+  }
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/hdinsight/package-info.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/hdinsight/package-info.java
new file mode 100644
index 0000000..1a8617b
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/hdinsight/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/**
+ * HD Insight driver bridge service launcher.
+ */
+package org.apache.reef.bridge.driver.launch.hdinsight;
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/local/LocalLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/local/LocalConfigurationProvider.java
similarity index 69%
rename from lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/local/LocalLauncher.java
rename to lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/local/LocalConfigurationProvider.java
index 63ed54f..ce6c693 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/local/LocalLauncher.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/local/LocalConfigurationProvider.java
@@ -20,32 +20,27 @@
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.reef.annotations.audience.Private;
-import org.apache.reef.bridge.driver.launch.BridgeDriverLauncher;
-import org.apache.reef.bridge.driver.service.DriverServiceConfigurationProvider;
+import org.apache.reef.bridge.driver.launch.RuntimeConfigurationProvider;
 import org.apache.reef.bridge.proto.ClientProtocol;
-import org.apache.reef.client.DriverLauncher;
-import org.apache.reef.client.LauncherStatus;
 import org.apache.reef.runtime.local.client.LocalRuntimeConfiguration;
-import org.apache.reef.tang.exceptions.InjectionException;
+import org.apache.reef.tang.Configuration;
 import org.apache.reef.tang.formats.ConfigurationModule;
 
 import javax.inject.Inject;
 
 /**
- * Submits a folder containing a Driver to the local runtime.
+ * Local runtime configuration provider.
  */
 @Private
-public final class LocalLauncher implements BridgeDriverLauncher {
-
-  private final DriverServiceConfigurationProvider driverServiceConfigurationProvider;
+public final class LocalConfigurationProvider implements RuntimeConfigurationProvider {
 
   @Inject
-  private LocalLauncher(final DriverServiceConfigurationProvider driverServiceConfigurationProvider) {
-    this.driverServiceConfigurationProvider = driverServiceConfigurationProvider;
+  private LocalConfigurationProvider() {
   }
 
-  public LauncherStatus launch(final ClientProtocol.DriverClientConfiguration driverClientConfiguration)
-      throws InjectionException {
+  @Override
+  public Configuration getRuntimeConfiguration(
+      final ClientProtocol.DriverClientConfiguration driverClientConfiguration) {
     ConfigurationModule localRuntimeCM = LocalRuntimeConfiguration.CONF;
     if (driverClientConfiguration.getLocalRuntime().getMaxNumberOfEvaluators() > 0) {
       localRuntimeCM = localRuntimeCM.set(LocalRuntimeConfiguration.MAX_NUMBER_OF_EVALUATORS,
@@ -63,8 +58,6 @@
       localRuntimeCM = localRuntimeCM.set(LocalRuntimeConfiguration.RUNTIME_ROOT_FOLDER,
           driverClientConfiguration.getDriverJobSubmissionDirectory());
     }
-    return DriverLauncher
-        .getLauncher(localRuntimeCM.build())
-        .run(driverServiceConfigurationProvider.getDriverServiceConfiguration(driverClientConfiguration));
+    return localRuntimeCM.build();
   }
 }
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/yarn/YarnConfigurationProvider.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/yarn/YarnConfigurationProvider.java
new file mode 100644
index 0000000..043132e
--- /dev/null
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/yarn/YarnConfigurationProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.bridge.driver.launch.yarn;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.reef.annotations.audience.Private;
+import org.apache.reef.bridge.driver.launch.RuntimeConfigurationProvider;
+import org.apache.reef.bridge.proto.ClientProtocol;
+import org.apache.reef.runtime.yarn.client.YarnClientConfiguration;
+import org.apache.reef.runtime.yarn.driver.parameters.FileSystemUrl;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.Configurations;
+import org.apache.reef.tang.JavaConfigurationBuilder;
+import org.apache.reef.tang.Tang;
+
+import javax.inject.Inject;
+
+/**
+ * This is runtime provider for YARN for submission from the bridge.
+ */
+@Private
+public final class YarnConfigurationProvider implements RuntimeConfigurationProvider {
+
+  @Inject
+  private YarnConfigurationProvider() {
+  }
+
+  public Configuration getRuntimeConfiguration(
+      final ClientProtocol.DriverClientConfiguration driverClientConfiguration) {
+    Configuration yarnConfiguration = YarnClientConfiguration.CONF
+        .set(YarnClientConfiguration.UNMANAGED_DRIVER,
+            driverClientConfiguration.getYarnRuntime().getUnmangedDriver())
+        .set(YarnClientConfiguration.YARN_PRIORITY, driverClientConfiguration.getYarnRuntime().getPriority())
+        .set(YarnClientConfiguration.JVM_HEAP_SLACK, 0.0)
+        .build();
+    if (StringUtils.isNotEmpty(driverClientConfiguration.getYarnRuntime().getFilesystemUrl())) {
+      final JavaConfigurationBuilder providerConfig = Tang.Factory.getTang().newConfigurationBuilder()
+          .bindNamedParameter(FileSystemUrl.class, driverClientConfiguration.getYarnRuntime().getFilesystemUrl());
+      yarnConfiguration = Configurations.merge(yarnConfiguration, providerConfig.build());
+    }
+    return yarnConfiguration;
+  }
+}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/yarn/YarnLauncher.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/yarn/YarnLauncher.java
deleted file mode 100644
index 58367ef..0000000
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/launch/yarn/YarnLauncher.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.reef.bridge.driver.launch.yarn;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.reef.annotations.audience.Private;
-import org.apache.reef.bridge.driver.launch.BridgeDriverLauncher;
-import org.apache.reef.bridge.driver.service.DriverServiceConfigurationProvider;
-import org.apache.reef.bridge.driver.service.grpc.GRPCDriverServiceConfigurationProvider;
-import org.apache.reef.bridge.proto.ClientProtocol;
-import org.apache.reef.client.DriverLauncher;
-import org.apache.reef.client.LauncherStatus;
-import org.apache.reef.runtime.yarn.client.YarnClientConfiguration;
-import org.apache.reef.runtime.yarn.driver.parameters.FileSystemUrl;
-import org.apache.reef.tang.Configuration;
-import org.apache.reef.tang.Configurations;
-import org.apache.reef.tang.JavaConfigurationBuilder;
-import org.apache.reef.tang.Tang;
-import org.apache.reef.tang.exceptions.InjectionException;
-
-import javax.inject.Inject;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * This is a bootstrap launcher for YARN for submission from the bridge. It allows for Java Driver
- * configuration generation directly on the Driver without need of Java dependency if REST
- * submission is used.
- */
-@Private
-public final class YarnLauncher implements BridgeDriverLauncher {
-  private static final Logger LOG = Logger.getLogger(YarnLauncher.class.getName());
-
-  @Inject
-  private YarnLauncher() {
-  }
-
-  public LauncherStatus launch(final ClientProtocol.DriverClientConfiguration driverClientConfiguration)
-      throws InjectionException {
-    final DriverServiceConfigurationProvider driverConfigurationProvider =
-        Tang.Factory.getTang().newInjector(Tang.Factory.getTang().newConfigurationBuilder()
-            .bindImplementation(DriverServiceConfigurationProvider.class,
-                GRPCDriverServiceConfigurationProvider.class)
-            .build()
-        ).getInstance(DriverServiceConfigurationProvider.class);
-    Configuration yarnConfiguration = YarnClientConfiguration.CONF
-        .set(YarnClientConfiguration.UNMANAGED_DRIVER,
-            driverClientConfiguration.getYarnRuntime().getUnmangedDriver())
-        .set(YarnClientConfiguration.YARN_PRIORITY, driverClientConfiguration.getYarnRuntime().getPriority())
-        .set(YarnClientConfiguration.JVM_HEAP_SLACK, 0.0)
-        .build();
-    if (StringUtils.isNotEmpty(driverClientConfiguration.getYarnRuntime().getFilesystemUrl())) {
-      final JavaConfigurationBuilder providerConfig = Tang.Factory.getTang().newConfigurationBuilder()
-          .bindNamedParameter(FileSystemUrl.class, driverClientConfiguration.getYarnRuntime().getFilesystemUrl());
-      yarnConfiguration = Configurations.merge(yarnConfiguration, providerConfig.build());
-    }
-    final LauncherStatus status = DriverLauncher.getLauncher(yarnConfiguration)
-        .run(driverConfigurationProvider.getDriverServiceConfiguration(driverClientConfiguration));
-    LOG.log(Level.INFO, "Job complete status: {0}", status);
-    if (status.getError().isPresent()) {
-      LOG.log(Level.SEVERE, "Job completed with error", status.getError().get());
-    }
-    return status;
-  }
-}
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverService.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverService.java
index b1bce16..4a7f6bd 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverService.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverService.java
@@ -29,7 +29,6 @@
 import org.apache.reef.driver.restart.DriverRestartCompleted;
 import org.apache.reef.driver.restart.DriverRestarted;
 import org.apache.reef.driver.task.*;
-import org.apache.reef.runtime.common.driver.idle.DriverIdlenessSource;
 import org.apache.reef.wake.time.event.StartTime;
 import org.apache.reef.wake.time.event.StopTime;
 
@@ -37,7 +36,7 @@
  * Interface implemented by a Driver Service.
  */
 @Private
-public interface DriverService extends DriverIdlenessSource {
+public interface DriverService {
 
   /**
    * Driver restart handler.
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverServiceConfiguration.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverServiceConfiguration.java
index be422a3..4ee1779 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverServiceConfiguration.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/DriverServiceConfiguration.java
@@ -25,13 +25,11 @@
 import org.apache.reef.driver.parameters.DriverIdleSources;
 import org.apache.reef.io.network.naming.NameServerConfiguration;
 import org.apache.reef.runtime.common.driver.client.JobStatusHandler;
+import org.apache.reef.runtime.common.driver.idle.DriverIdlenessSource;
 import org.apache.reef.tang.Configuration;
 import org.apache.reef.tang.Configurations;
 import org.apache.reef.tang.Tang;
-import org.apache.reef.tang.formats.ConfigurationModule;
-import org.apache.reef.tang.formats.ConfigurationModuleBuilder;
-import org.apache.reef.tang.formats.RequiredImpl;
-import org.apache.reef.tang.formats.RequiredParameter;
+import org.apache.reef.tang.formats.*;
 import org.apache.reef.webserver.HttpHandlerConfiguration;
 import org.apache.reef.webserver.HttpServerReefEventHandler;
 import org.apache.reef.webserver.ReefEventStateManager;
@@ -46,11 +44,13 @@
 
   public static final RequiredParameter<String> DRIVER_CLIENT_COMMAND = new RequiredParameter<>();
 
+  public static final OptionalImpl<DriverIdlenessSource> DRIVER_IDLENESS_SOURCES = new OptionalImpl<>();
+
   /** Configuration module that binds all driver handlers. */
   public static final ConfigurationModule CONF = new DriverServiceConfiguration()
       .bindImplementation(DriverService.class, DRIVER_SERVICE_IMPL)
       .bindNamedParameter(DriverClientCommand.class, DRIVER_CLIENT_COMMAND)
-      .bindSetEntry(DriverIdleSources.class, DriverService.class)
+      .bindSetEntry(DriverIdleSources.class, DRIVER_IDLENESS_SOURCES)
       .build();
 
   public static final ConfigurationModule STATIC_DRIVER_CONF_MODULE = DriverConfiguration.CONF
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverService.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverService.java
index 4d39bb3..75106b8 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverService.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverService.java
@@ -19,29 +19,36 @@
 package org.apache.reef.bridge.driver.service.grpc;
 
 import com.google.protobuf.ByteString;
-import io.grpc.*;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Server;
+import io.grpc.Status;
+import io.grpc.netty.NettyServerBuilder;
 import io.grpc.stub.StreamObserver;
 import org.apache.commons.lang.StringUtils;
 import org.apache.reef.annotations.audience.Private;
 import org.apache.reef.bridge.driver.common.grpc.GRPCUtils;
 import org.apache.reef.bridge.driver.common.grpc.ObserverCleanup;
-import org.apache.reef.bridge.driver.service.DriverClientException;
 import org.apache.reef.bridge.driver.service.DriverService;
-import org.apache.reef.bridge.service.parameters.DriverClientCommand;
 import org.apache.reef.bridge.proto.*;
 import org.apache.reef.bridge.proto.Void;
-import org.apache.reef.driver.context.*;
+import org.apache.reef.bridge.service.parameters.DriverClientCommand;
+import org.apache.reef.driver.context.ActiveContext;
+import org.apache.reef.driver.context.ClosedContext;
+import org.apache.reef.driver.context.ContextMessage;
+import org.apache.reef.driver.context.FailedContext;
 import org.apache.reef.driver.evaluator.*;
 import org.apache.reef.driver.restart.DriverRestartCompleted;
 import org.apache.reef.driver.restart.DriverRestarted;
 import org.apache.reef.driver.task.*;
+import org.apache.reef.exception.NonSerializableException;
 import org.apache.reef.runtime.common.driver.context.EvaluatorContext;
 import org.apache.reef.runtime.common.driver.evaluator.AllocatedEvaluatorImpl;
+import org.apache.reef.runtime.common.driver.idle.DriverIdlenessSource;
 import org.apache.reef.runtime.common.driver.idle.IdleMessage;
 import org.apache.reef.runtime.common.files.REEFFileNames;
 import org.apache.reef.runtime.common.utils.ExceptionCodec;
 import org.apache.reef.tang.annotations.Parameter;
-import org.apache.reef.tang.formats.ConfigurationSerializer;
 import org.apache.reef.util.OSUtils;
 import org.apache.reef.util.Optional;
 import org.apache.reef.wake.EventHandler;
@@ -53,6 +60,7 @@
 
 import javax.inject.Inject;
 import java.io.*;
+import java.net.InetSocketAddress;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -68,7 +76,7 @@
  * GRPC DriverBridgeService that interacts with higher-level languages.
  */
 @Private
-public final class GRPCDriverService implements DriverService {
+public final class GRPCDriverService implements DriverService, DriverIdlenessSource {
   private static final Logger LOG = Logger.getLogger(GRPCDriverService.class.getName());
 
   private static final Void VOID = Void.newBuilder().build();
@@ -87,14 +95,14 @@
 
   private final ExceptionCodec exceptionCodec;
 
-  private final ConfigurationSerializer configurationSerializer;
-
   private final EvaluatorRequestor evaluatorRequestor;
 
   private final JVMProcessFactory jvmProcessFactory;
 
   private final CLRProcessFactory clrProcessFactory;
 
+  private final DotNetProcessFactory dotNetProcessFactory;
+
   private final TcpPortProvider tcpPortProvider;
 
   private final String driverClientCommand;
@@ -112,18 +120,18 @@
       final Clock clock,
       final REEFFileNames reefFileNames,
       final EvaluatorRequestor evaluatorRequestor,
-      final ConfigurationSerializer configurationSerializer,
       final JVMProcessFactory jvmProcessFactory,
       final CLRProcessFactory clrProcessFactory,
+      final DotNetProcessFactory dotNetProcessFactory,
       final TcpPortProvider tcpPortProvider,
       final ExceptionCodec exceptionCodec,
       @Parameter(DriverClientCommand.class) final String driverClientCommand) {
     this.clock = clock;
     this.reefFileNames = reefFileNames;
     this.exceptionCodec = exceptionCodec;
-    this.configurationSerializer = configurationSerializer;
     this.jvmProcessFactory = jvmProcessFactory;
     this.clrProcessFactory = clrProcessFactory;
+    this.dotNetProcessFactory = dotNetProcessFactory;
     this.evaluatorRequestor = evaluatorRequestor;
     this.driverClientCommand = driverClientCommand;
     this.tcpPortProvider = tcpPortProvider;
@@ -132,7 +140,7 @@
   private void start() throws IOException, InterruptedException {
     for (final int port : this.tcpPortProvider) {
       try {
-        this.server = ServerBuilder.forPort(port)
+        this.server = NettyServerBuilder.forAddress(new InetSocketAddress("localhost", port))
             .addService(new DriverBridgeServiceImpl())
             .build()
             .start();
@@ -155,21 +163,21 @@
         .redirectOutput(new File(this.reefFileNames.getDriverClientStdoutFileName()))
         .start();
     synchronized (this) {
-      int attempts = 30; // give some time
+      int attempts = 60; // give it a minute
       /* wait for driver client process to register
        * Note: attempts and wait time have been given reasonable hardcoded values for a driver
        * client to register with the driver service (us). Making these values configurable would
        * require additions to the ClientProtocol buffer such that they can be passed to the
        * GRPCDriverServiceConfigurationProvider and bound to the appropriate NamedParameters. It
        * is the opinion at the time of this writing that a driver client should be able to register
-       * within 10 seconds.
+       * within a minute.
        */
-      while (attempts-- > 0 && this.clientStub == null && driverProcessIsAlive()) {
+      while (!stopped && attempts-- > 0 && this.clientStub == null && driverProcessIsAlive()) {
         LOG.log(Level.INFO, "waiting for driver process to register");
         this.wait(1000); // a second
       }
     }
-    if (driverProcessIsAlive()) {
+    if (!stopped && driverProcessIsAlive()) {
       final Thread closeChildThread = new Thread() {
         public void run() {
           synchronized (GRPCDriverService.this) {
@@ -213,6 +221,7 @@
         }
       } finally {
         LOG.log(Level.INFO, "COMPLETED STOP: gRPC Driver Service");
+        clientStub = null;
         stopped = true;
       }
     }
@@ -280,38 +289,43 @@
   @Override
   public IdleMessage getIdleStatus() {
     final String componentName = "Java Bridge DriverService";
-    if (this.clientStub != null) {
-      try {
-        final IdleStatus idleStatus = this.clientStub.idlenessCheckHandler(VOID).get();
-        LOG.log(Level.INFO, "is idle: {0}", idleStatus.getIsIdle());
-        return new IdleMessage(
-            componentName,
-            idleStatus.getReason(),
-            idleStatus.getIsIdle());
-      } catch (final ExecutionException | InterruptedException e) {
-        stop(e);
+    synchronized (this) {
+      if (this.clientStub != null) {
+        try {
+          LOG.log(Level.INFO, "{0} getting idle status", componentName);
+          final IdleStatus idleStatus = this.clientStub.idlenessCheckHandler(VOID).get();
+          LOG.log(Level.INFO, "is idle: {0}", idleStatus.getIsIdle());
+          return new IdleMessage(
+              componentName,
+              idleStatus.getReason(),
+              idleStatus.getIsIdle());
+        } catch (final ExecutionException | InterruptedException e) {
+          stop(e);
+        }
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
+      return new IdleMessage(
+          componentName,
+          "stub not initialized",
+          true);
     }
-    return new IdleMessage(
-        componentName,
-        "stub not initialized",
-        true);
   }
 
   @Override
   public void startHandler(final StartTime startTime) {
     try {
       start();
-      synchronized (this) {
-        if (this.clientStub != null) {
-          this.clientStub.startHandler(
-              StartTimeInfo.newBuilder().setStartTime(startTime.getTimestamp()).build());
-        } else {
-          stop(new IllegalStateException("Unable to start driver client"));
-        }
-      }
     } catch (final IOException | InterruptedException e) {
-      stop(e);
+      throw new RuntimeException("unable to start driver client", e);
+    }
+    synchronized (this) {
+      if (this.clientStub != null) {
+        this.clientStub.startHandler(
+            StartTimeInfo.newBuilder().setStartTime(startTime.getTimestamp()).build());
+      } else if (!stopped) {
+        stop(new RuntimeException("Unable to start driver client"));
+      }
     }
   }
 
@@ -319,6 +333,7 @@
   public void stopHandler(final StopTime stopTime) {
     synchronized (this) {
       if (clientStub != null) {
+        LOG.log(Level.INFO, "Stop handler called at {0}", stopTime);
         final Future<ExceptionInfo> callCompletion = this.clientStub.stopHandler(
             StopTimeInfo.newBuilder().setStopTime(stopTime.getTimestamp()).build());
         try {
@@ -329,7 +344,8 @@
               throw new RuntimeException("driver stop exception",
                   t.get().getCause() != null ? t.get().getCause() : t.get());
             } else {
-              throw new RuntimeException(error.getMessage() != null ? error.getMessage() : error.getName());
+              throw new RuntimeException(error.getName(),
+                  new NonSerializableException(error.getMessage(), error.getData().toByteArray()));
             }
           }
         } catch (final TimeoutException e) {
@@ -339,6 +355,8 @@
         } finally {
           stop();
         }
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
     }
   }
@@ -346,200 +364,263 @@
   @Override
   public void allocatedEvaluatorHandler(final AllocatedEvaluator eval) {
     synchronized (this) {
-      this.allocatedEvaluatorMap.put(eval.getId(), eval);
-      this.clientStub.allocatedEvaluatorHandler(
-          EvaluatorInfo.newBuilder()
-              .setEvaluatorId(eval.getId())
-              .setDescriptorInfo(
-                  GRPCUtils.toEvaluatorDescriptorInfo(eval.getEvaluatorDescriptor()))
-              .build());
+      if (this.clientStub != null) {
+        this.allocatedEvaluatorMap.put(eval.getId(), eval);
+        this.clientStub.allocatedEvaluatorHandler(
+            EvaluatorInfo.newBuilder()
+                .setEvaluatorId(eval.getId())
+                .setDescriptorInfo(
+                    GRPCUtils.toEvaluatorDescriptorInfo(eval.getEvaluatorDescriptor()))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void completedEvaluatorHandler(final CompletedEvaluator eval) {
     synchronized (this) {
-      this.allocatedEvaluatorMap.remove(eval.getId());
-      this.clientStub.completedEvaluatorHandler(
-          EvaluatorInfo.newBuilder().setEvaluatorId(eval.getId()).build());
+      if (this.clientStub != null) {
+        this.allocatedEvaluatorMap.remove(eval.getId());
+        this.clientStub.completedEvaluatorHandler(
+            EvaluatorInfo.newBuilder().setEvaluatorId(eval.getId()).build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void failedEvaluatorHandler(final FailedEvaluator eval) {
     synchronized (this) {
-      this.allocatedEvaluatorMap.remove(eval.getId());
-      this.clientStub.failedEvaluatorHandler(
-          EvaluatorInfo.newBuilder().setEvaluatorId(eval.getId()).build());
+      if (this.clientStub != null) {
+        this.allocatedEvaluatorMap.remove(eval.getId());
+        this.clientStub.failedEvaluatorHandler(
+            EvaluatorInfo.newBuilder().setEvaluatorId(eval.getId()).build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void activeContextHandler(final ActiveContext context) {
     synchronized (this) {
-      this.activeContextMap.put(context.getId(), context);
-      this.clientStub.activeContextHandler(GRPCUtils.toContextInfo(context));
+      if (this.clientStub != null) {
+        this.activeContextMap.put(context.getId(), context);
+        this.clientStub.activeContextHandler(GRPCUtils.toContextInfo(context));
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void closedContextHandler(final ClosedContext context) {
     synchronized (this) {
-      this.activeContextMap.remove(context.getId());
-      this.clientStub.closedContextHandler(GRPCUtils.toContextInfo(context));
+      if (this.clientStub != null) {
+        this.activeContextMap.remove(context.getId());
+        this.clientStub.closedContextHandler(GRPCUtils.toContextInfo(context));
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void failedContextHandler(final FailedContext context) {
     synchronized (this) {
-      final ExceptionInfo error;
-      if (context.getReason().isPresent()) {
-        final Throwable reason = context.getReason().get();
-        error = GRPCUtils.createExceptionInfo(this.exceptionCodec, reason);
-      } else if (context.getData().isPresent()) {
-        error = ExceptionInfo.newBuilder()
-            .setName(context.toString())
-            .setMessage(context.getDescription().orElse(
-                context.getMessage() != null ? context.getMessage() : ""))
-            .setData(ByteString.copyFrom(context.getData().get()))
-            .build();
+      if (this.clientStub != null) {
+        final ExceptionInfo error;
+        if (context.getReason().isPresent()) {
+          final Throwable reason = context.getReason().get();
+          error = GRPCUtils.createExceptionInfo(this.exceptionCodec, reason);
+        } else if (context.getData().isPresent()) {
+          error = ExceptionInfo.newBuilder()
+              .setName(context.toString())
+              .setMessage(context.getDescription().orElse(
+                  context.getMessage() != null ? context.getMessage() : ""))
+              .setData(ByteString.copyFrom(context.getData().get()))
+              .build();
+        } else {
+          error = GRPCUtils.createExceptionInfo(this.exceptionCodec, context.asError());
+        }
+        this.activeContextMap.remove(context.getId());
+        this.clientStub.failedContextHandler(GRPCUtils.toContextInfo(context, error));
       } else {
-        error = GRPCUtils.createExceptionInfo(this.exceptionCodec, context.asError());
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
-      this.activeContextMap.remove(context.getId());
-      this.clientStub.failedContextHandler(GRPCUtils.toContextInfo(context, error));
     }
   }
 
   @Override
   public void contextMessageHandler(final ContextMessage message) {
     synchronized (this) {
-      this.clientStub.contextMessageHandler(
-          ContextMessageInfo.newBuilder()
-              .setContextId(message.getId())
-              .setMessageSourceId(message.getMessageSourceID())
-              .setSequenceNumber(message.getSequenceNumber())
-              .setPayload(ByteString.copyFrom(message.get()))
-              .build());
+      if (this.clientStub != null) {
+        this.clientStub.contextMessageHandler(
+            ContextMessageInfo.newBuilder()
+                .setContextId(message.getId())
+                .setMessageSourceId(message.getMessageSourceID())
+                .setSequenceNumber(message.getSequenceNumber())
+                .setPayload(ByteString.copyFrom(message.get()))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void runningTaskHandler(final RunningTask task) {
     synchronized (this) {
-      final ActiveContext context = task.getActiveContext();
-      if (!this.activeContextMap.containsKey(context.getId())) {
-        this.activeContextMap.put(context.getId(), context);
+      if (this.clientStub != null) {
+        final ActiveContext context = task.getActiveContext();
+        if (!this.activeContextMap.containsKey(context.getId())) {
+          this.activeContextMap.put(context.getId(), context);
+        }
+        this.runningTaskMap.put(task.getId(), task);
+        this.clientStub.runningTaskHandler(
+            TaskInfo.newBuilder()
+                .setTaskId(task.getId())
+                .setContext(GRPCUtils.toContextInfo(context))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
-      this.runningTaskMap.put(task.getId(), task);
-      this.clientStub.runningTaskHandler(
-          TaskInfo.newBuilder()
-              .setTaskId(task.getId())
-              .setContext(GRPCUtils.toContextInfo(context))
-              .build());
     }
   }
 
   @Override
   public void failedTaskHandler(final FailedTask task) {
     synchronized (this) {
-      if (task.getActiveContext().isPresent() &&
-          !this.activeContextMap.containsKey(task.getActiveContext().get().getId())) {
-        this.activeContextMap.put(task.getActiveContext().get().getId(), task.getActiveContext().get());
-      }
-      final TaskInfo.Builder taskInfoBuilder = TaskInfo.newBuilder()
-          .setTaskId(task.getId());
-      if (task.getActiveContext().isPresent()) {
-        taskInfoBuilder.setContext(GRPCUtils.toContextInfo(task.getActiveContext().get()));
-      }
-      if (task.getReason().isPresent()) {
-        taskInfoBuilder.setException(GRPCUtils.createExceptionInfo(this.exceptionCodec, task.getReason().get()));
-      } else if (task.getData().isPresent()) {
-        final Throwable reason = task.asError();
-        taskInfoBuilder.setException(ExceptionInfo.newBuilder()
-            .setName(reason.toString())
-            .setMessage(task.getMessage() != null ? task.getMessage() : "")
-            .setData(ByteString.copyFrom(task.getData().get()))
-            .build());
+      if (this.clientStub != null) {
+        if (task.getActiveContext().isPresent() &&
+            !this.activeContextMap.containsKey(task.getActiveContext().get().getId())) {
+          this.activeContextMap.put(task.getActiveContext().get().getId(), task.getActiveContext().get());
+        }
+        final TaskInfo.Builder taskInfoBuilder = TaskInfo.newBuilder()
+            .setTaskId(task.getId());
+        if (task.getActiveContext().isPresent()) {
+          taskInfoBuilder.setContext(GRPCUtils.toContextInfo(task.getActiveContext().get()));
+        }
+        if (task.getReason().isPresent()) {
+          LOG.log(Level.WARNING, "Task exception present", task.getReason().get());
+          taskInfoBuilder.setException(GRPCUtils.createExceptionInfo(this.exceptionCodec, task.getReason().get()));
+        } else if (task.getData().isPresent()) {
+          LOG.log(Level.WARNING, "Not able to deserialize task exception {0}", task.getMessage());
+          final Throwable reason = task.asError();
+          taskInfoBuilder.setException(ExceptionInfo.newBuilder()
+              .setName(reason.toString())
+              .setMessage(StringUtils.isNotEmpty(task.getMessage()) ? task.getMessage() : reason.toString())
+              .setData(ByteString.copyFrom(task.getData().get()))
+              .build());
+        } else {
+          LOG.log(Level.WARNING, "Serialize generic error");
+          taskInfoBuilder.setException(GRPCUtils.createExceptionInfo(this.exceptionCodec, task.asError()));
+        }
+        this.runningTaskMap.remove(task.getId());
+        this.clientStub.failedTaskHandler(taskInfoBuilder.build());
       } else {
-        taskInfoBuilder.setException(GRPCUtils.createExceptionInfo(this.exceptionCodec, task.asError()));
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
-      this.runningTaskMap.remove(task.getId());
-      this.clientStub.failedTaskHandler(taskInfoBuilder.build());
     }
   }
 
   @Override
   public void completedTaskHandler(final CompletedTask task) {
     synchronized (this) {
-      if (!this.activeContextMap.containsKey(task.getActiveContext().getId())) {
-        this.activeContextMap.put(task.getActiveContext().getId(), task.getActiveContext());
+      if (this.clientStub != null) {
+        if (!this.activeContextMap.containsKey(task.getActiveContext().getId())) {
+          this.activeContextMap.put(task.getActiveContext().getId(), task.getActiveContext());
+        }
+        this.runningTaskMap.remove(task.getId());
+        this.clientStub.completedTaskHandler(
+            TaskInfo.newBuilder()
+                .setTaskId(task.getId())
+                .setContext(GRPCUtils.toContextInfo(task.getActiveContext()))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
-      this.runningTaskMap.remove(task.getId());
-      this.clientStub.completedTaskHandler(
-          TaskInfo.newBuilder()
-              .setTaskId(task.getId())
-              .setContext(GRPCUtils.toContextInfo(task.getActiveContext()))
-              .build());
     }
   }
 
   @Override
   public void suspendedTaskHandler(final SuspendedTask task) {
     synchronized (this) {
-      if (!this.activeContextMap.containsKey(task.getActiveContext().getId())) {
-        this.activeContextMap.put(task.getActiveContext().getId(), task.getActiveContext());
+      if (this.clientStub != null) {
+        if (!this.activeContextMap.containsKey(task.getActiveContext().getId())) {
+          this.activeContextMap.put(task.getActiveContext().getId(), task.getActiveContext());
+        }
+        this.runningTaskMap.remove(task.getId());
+        this.clientStub.suspendedTaskHandler(
+            TaskInfo.newBuilder()
+                .setTaskId(task.getId())
+                .setContext(GRPCUtils.toContextInfo(task.getActiveContext()))
+                .setResult(task.get() == null || task.get().length == 0 ?
+                    null : ByteString.copyFrom(task.get()))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
       }
-      this.runningTaskMap.remove(task.getId());
-      this.clientStub.suspendedTaskHandler(
-          TaskInfo.newBuilder()
-              .setTaskId(task.getId())
-              .setContext(GRPCUtils.toContextInfo(task.getActiveContext()))
-              .setResult(task.get() == null || task.get().length == 0 ?
-                  null : ByteString.copyFrom(task.get()))
-              .build());
     }
   }
 
   @Override
   public void taskMessageHandler(final TaskMessage message) {
     synchronized (this) {
-      this.clientStub.taskMessageHandler(
-          TaskMessageInfo.newBuilder()
-              .setTaskId(message.getId())
-              .setContextId(message.getContextId())
-              .setMessageSourceId(message.getMessageSourceID())
-              .setSequenceNumber(message.getSequenceNumber())
-              .setPayload(ByteString.copyFrom(message.get()))
-              .build());
+      if (this.clientStub != null) {
+        this.clientStub.taskMessageHandler(
+            TaskMessageInfo.newBuilder()
+                .setTaskId(message.getId())
+                .setContextId(message.getContextId())
+                .setMessageSourceId(message.getMessageSourceID())
+                .setSequenceNumber(message.getSequenceNumber())
+                .setPayload(ByteString.copyFrom(message.get()))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void clientMessageHandler(final byte[] message) {
     synchronized (this) {
-      this.clientStub.clientMessageHandler(
-          ClientMessageInfo.newBuilder()
-              .setPayload(ByteString.copyFrom(message))
-              .build());
+      if (this.clientStub != null) {
+        this.clientStub.clientMessageHandler(
+            ClientMessageInfo.newBuilder()
+                .setPayload(ByteString.copyFrom(message))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void clientCloseHandler() {
     synchronized (this) {
-      this.clientStub.clientCloseHandler(VOID);
+      if (this.clientStub != null) {
+        this.clientStub.clientCloseHandler(VOID);
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
   @Override
   public void clientCloseWithMessageHandler(final byte[] message) {
     synchronized (this) {
-      this.clientStub.clientCloseWithMessageHandler(
-          ClientMessageInfo.newBuilder()
-              .setPayload(ByteString.copyFrom(message))
-              .build());
+      if (this.clientStub != null) {
+        this.clientStub.clientCloseWithMessageHandler(
+            ClientMessageInfo.newBuilder()
+                .setPayload(ByteString.copyFrom(message))
+                .build());
+      } else {
+        LOG.log(Level.WARNING, "client shutdown has already completed");
+      }
     }
   }
 
@@ -547,74 +628,90 @@
   public void driverRestarted(final DriverRestarted restart) {
     try {
       start();
-      synchronized (this) {
-        if (this.clientStub != null) {
-          this.clientStub.driverRestartHandler(DriverRestartInfo.newBuilder()
-              .setResubmissionAttempts(restart.getResubmissionAttempts())
-              .setStartTime(StartTimeInfo.newBuilder()
-                  .setStartTime(restart.getStartTime().getTimestamp()).build())
-              .addAllExpectedEvaluatorIds(restart.getExpectedEvaluatorIds())
-              .build());
-        } else {
-          stop(new DriverClientException("Failed to restart driver client"));
-        }
-      }
     } catch (final InterruptedException | IOException e) {
-      stop(e);
+      throw new RuntimeException("unable to start driver client", e);
+    }
+    synchronized (this) {
+      if (this.clientStub != null) {
+        this.clientStub.driverRestartHandler(DriverRestartInfo.newBuilder()
+            .setResubmissionAttempts(restart.getResubmissionAttempts())
+            .setStartTime(StartTimeInfo.newBuilder()
+                .setStartTime(restart.getStartTime().getTimestamp()).build())
+            .addAllExpectedEvaluatorIds(restart.getExpectedEvaluatorIds())
+            .build());
+      } else {
+        throw new RuntimeException("client stub not running");
+      }
     }
   }
 
   @Override
   public void restartRunningTask(final RunningTask task) {
     synchronized (this) {
-      final ActiveContext context = task.getActiveContext();
-      if (!this.activeContextMap.containsKey(context.getId())) {
-        this.activeContextMap.put(context.getId(), context);
+      if (this.clientStub != null) {
+        final ActiveContext context = task.getActiveContext();
+        if (!this.activeContextMap.containsKey(context.getId())) {
+          this.activeContextMap.put(context.getId(), context);
+        }
+        this.runningTaskMap.put(task.getId(), task);
+        this.clientStub.driverRestartRunningTaskHandler(
+            TaskInfo.newBuilder()
+                .setTaskId(task.getId())
+                .setContext(GRPCUtils.toContextInfo(context))
+                .build());
+      } else {
+        throw new RuntimeException("client stub not running");
       }
-      this.runningTaskMap.put(task.getId(), task);
-      this.clientStub.driverRestartRunningTaskHandler(
-          TaskInfo.newBuilder()
-              .setTaskId(task.getId())
-              .setContext(GRPCUtils.toContextInfo(context))
-              .build());
     }
   }
 
   @Override
   public void restartActiveContext(final ActiveContext context) {
     synchronized (this) {
-      this.activeContextMap.put(context.getId(), context);
-      this.clientStub.driverRestartActiveContextHandler(
-          GRPCUtils.toContextInfo(context));
+      if (this.clientStub != null) {
+        this.activeContextMap.put(context.getId(), context);
+        this.clientStub.driverRestartActiveContextHandler(
+            GRPCUtils.toContextInfo(context));
+      } else {
+        throw new RuntimeException("client stub not running");
+      }
     }
   }
 
   @Override
   public void driverRestartCompleted(final DriverRestartCompleted restartCompleted) {
     synchronized (this) {
-      this.clientStub.driverRestartCompletedHandler(DriverRestartCompletedInfo.newBuilder()
-          .setCompletionTime(StopTimeInfo.newBuilder()
-              .setStopTime(restartCompleted.getCompletedTime().getTimestamp()).build())
-          .setIsTimedOut(restartCompleted.isTimedOut())
-          .build());
+      if (this.clientStub != null) {
+        this.clientStub.driverRestartCompletedHandler(DriverRestartCompletedInfo.newBuilder()
+            .setCompletionTime(StopTimeInfo.newBuilder()
+                .setStopTime(restartCompleted.getCompletedTime().getTimestamp()).build())
+            .setIsTimedOut(restartCompleted.isTimedOut())
+            .build());
+      } else {
+        throw new RuntimeException("client stub not running");
+      }
     }
   }
 
   @Override
   public void restartFailedEvalautor(final FailedEvaluator evaluator) {
     synchronized (this) {
-      this.clientStub.driverRestartFailedEvaluatorHandler(EvaluatorInfo.newBuilder()
-          .setEvaluatorId(evaluator.getId())
-          .setFailure(EvaluatorInfo.FailureInfo.newBuilder()
-              .setMessage(evaluator.getEvaluatorException() != null ?
-                  evaluator.getEvaluatorException().getMessage() : "unknown failure during restart")
-              .build())
-          .build());
+      if (this.clientStub != null) {
+        this.clientStub.driverRestartFailedEvaluatorHandler(EvaluatorInfo.newBuilder()
+            .setEvaluatorId(evaluator.getId())
+            .setFailure(EvaluatorInfo.FailureInfo.newBuilder()
+                .setMessage(evaluator.getEvaluatorException() != null ?
+                    evaluator.getEvaluatorException().getMessage() : "unknown failure during restart")
+                .build())
+            .build());
+      } else {
+        throw new RuntimeException("client stub not running");
+      }
     }
   }
 
   private Optional<Throwable> parseException(final ExceptionInfo info) {
-    if (info.getData() == null || info.getData().isEmpty()) {
+    if (info.getData().isEmpty()) {
       return Optional.empty();
     } else {
       return exceptionCodec.fromBytes(info.getData().toByteArray());
@@ -629,29 +726,31 @@
         final DriverClientRegistration request,
         final StreamObserver<Void> responseObserver) {
       LOG.log(Level.INFO, "driver client register");
-      try (final ObserverCleanup _cleanup = ObserverCleanup.of(responseObserver)) {
-        if (request.hasException()) {
-          LOG.log(Level.SEVERE, "Driver client initialization exception");
-          final Optional<Throwable> ex = parseException(request.getException());
-          if (ex.isPresent()) {
-            GRPCDriverService.this.clock.stop(ex.get());
+      synchronized (GRPCDriverService.this) {
+        try (final ObserverCleanup _cleanup = ObserverCleanup.of(responseObserver)) {
+          if (request.hasException()) {
+            LOG.log(Level.SEVERE, "Driver client initialization exception");
+            final Optional<Throwable> optionalEx = parseException(request.getException());
+            final Throwable ex;
+            if (optionalEx.isPresent()) {
+              ex = optionalEx.get();
+            } else if (!request.getException().getData().isEmpty()) {
+              ex = new NonSerializableException(request.getException().getMessage(),
+                  request.getException().getData().toByteArray());
+            } else {
+              ex = new RuntimeException(request.getException().getMessage());
+            }
+            stop(ex);
           } else {
-            GRPCDriverService.this.clock.stop(new RuntimeException(
-                request.getException().getMessage() == null ?
-                    request.getException().getName() :
-                    request.getException().getMessage()
-            ));
-          }
-        } else {
-          final ManagedChannel channel = ManagedChannelBuilder
-              .forAddress(request.getHost(), request.getPort())
-              .usePlaintext()
-              .build();
-          synchronized (GRPCDriverService.this) {
+            final ManagedChannel channel = ManagedChannelBuilder
+                .forAddress(request.getHost(), request.getPort())
+                .usePlaintext()
+                .build();
             GRPCDriverService.this.clientStub = DriverClientGrpc.newFutureStub(channel);
-            GRPCDriverService.this.notifyAll();
+            LOG.log(Level.INFO, "Driver has registered on port {0}", request.getPort());
           }
-          LOG.log(Level.INFO, "Driver has registered on port {0}", request.getPort());
+        } finally {
+          GRPCDriverService.this.notifyAll();
         }
       }
     }
@@ -695,7 +794,9 @@
           } else {
             // exception that cannot be parsed in java
             GRPCDriverService.this.clock.stop(
-                new DriverClientException(request.getException().getMessage()));
+                new NonSerializableException(
+                    request.getException().getMessage(),
+                    request.getException().getData().toByteArray()));
           }
         } else {
           LOG.log(Level.INFO, "clean shutdown");
@@ -734,99 +835,102 @@
         final AllocatedEvaluatorRequest request,
         final StreamObserver<Void> responseObserver) {
       try (final ObserverCleanup _cleanup = ObserverCleanup.of(responseObserver)) {
-        if (request.getEvaluatorConfiguration() == null) {
-          responseObserver.onError(Status.INTERNAL
-              .withDescription("Evaluator configuration required")
-              .asRuntimeException());
-        } else if (request.getContextConfiguration() == null && request.getTaskConfiguration() == null) {
-          responseObserver.onError(Status.INTERNAL
-              .withDescription("Context and/or Task configuration required")
-              .asRuntimeException());
-        } else {
-          synchronized (GRPCDriverService.this) {
-            if (!GRPCDriverService.this.allocatedEvaluatorMap.containsKey(request.getEvaluatorId())) {
-              responseObserver.onError(Status.INTERNAL
-                  .withDescription("Unknown allocated evaluator " + request.getEvaluatorId())
-                  .asRuntimeException());
+        synchronized (GRPCDriverService.this) {
+          final AllocatedEvaluator evaluator =
+              GRPCDriverService.this.allocatedEvaluatorMap.get(request.getEvaluatorId());
+          if (evaluator == null) {
+            responseObserver.onError(Status.INTERNAL
+                .withDescription("Unknown allocated evaluator " + request.getEvaluatorId())
+                .asRuntimeException());
+            return;
+          }
+          // Close evaluator?
+          if (request.getCloseEvaluator()) {
+            evaluator.close();
+            return;
+          }
+
+          // Ensure context and/or task
+          if (StringUtils.isEmpty(request.getContextConfiguration()) &&
+              StringUtils.isEmpty(request.getTaskConfiguration())) {
+            responseObserver.onError(Status.INTERNAL
+                .withDescription("Context and/or Task configuration required")
+                .asRuntimeException());
+            return;
+          }
+          for (final String file : request.getAddFilesList()) {
+            evaluator.addFile(new File(file));
+          }
+          for (final String library : request.getAddLibrariesList()) {
+            evaluator.addLibrary(new File(library));
+          }
+          if (request.hasSetProcess()) {
+            final AllocatedEvaluatorRequest.EvaluatorProcessRequest processRequest =
+                request.getSetProcess();
+            switch (processRequest.getProcessType()) {
+            case JVM:
+              LOG.log(Level.INFO, "Setting JVM Process");
+              setJVMProcess(evaluator, processRequest);
+              break;
+            case CLR:
+              LOG.log(Level.INFO, "Setting CLR Process");
+              setEvaluatorProcess(evaluator, clrProcessFactory.newEvaluatorProcess(), processRequest);
+              break;
+            case DOTNET:
+              LOG.log(Level.INFO, "Setting DOTNET Process");
+              setEvaluatorProcess(evaluator, dotNetProcessFactory.newEvaluatorProcess(), processRequest);
+              break;
+            default:
+              throw new RuntimeException("Unknown evaluator process type");
             }
-            final AllocatedEvaluator evaluator =
-                GRPCDriverService.this.allocatedEvaluatorMap.get(request.getEvaluatorId());
-            if (request.getCloseEvaluator()) {
-              evaluator.close();
+          }
+          final String evaluatorConfiguration = StringUtils.isNotEmpty(request.getEvaluatorConfiguration()) ?
+              request.getEvaluatorConfiguration() : null;
+          final String contextConfiguration = StringUtils.isNotEmpty(request.getContextConfiguration()) ?
+              request.getContextConfiguration() : null;
+          final String serviceConfiguration = StringUtils.isNotEmpty(request.getServiceConfiguration()) ?
+              request.getServiceConfiguration() : null;
+          final String taskConfiguration = StringUtils.isNotEmpty(request.getTaskConfiguration()) ?
+              request.getTaskConfiguration() : null;
+          if (contextConfiguration != null && taskConfiguration != null) {
+            if (serviceConfiguration == null) {
+              LOG.log(Level.INFO, "Submitting evaluator with context and task");
+              ((AllocatedEvaluatorImpl) evaluator).submitContextAndTask(
+                  evaluatorConfiguration,
+                  contextConfiguration,
+                  taskConfiguration);
             } else {
-              for (final String file : request.getAddFilesList()) {
-                evaluator.addFile(new File(file));
-              }
-              for (final String library : request.getAddLibrariesList()) {
-                evaluator.addLibrary(new File(library));
-              }
-              if (request.getSetProcess() != null) {
-                final AllocatedEvaluatorRequest.EvaluatorProcessRequest processRequest =
-                    request.getSetProcess();
-                switch (evaluator.getEvaluatorDescriptor().getProcess().getType()) {
-                case JVM:
-                  setJVMProcess(evaluator, processRequest);
-                  break;
-                case CLR:
-                  setCLRProcess(evaluator, processRequest);
-                  break;
-                default:
-                  throw new RuntimeException("Unknown evaluator process type");
-                }
-              }
-              if (StringUtils.isEmpty(request.getEvaluatorConfiguration())) {
-                // Assume that we are running Java driver client, but this assumption could be a bug so log a warning
-                LOG.log(Level.WARNING, "No evaluator configuration detected. Assuming a Java driver client.");
-                if (StringUtils.isNotEmpty(request.getContextConfiguration()) &&
-                    StringUtils.isNotEmpty(request.getTaskConfiguration())) {
-                  // submit context and task
-                  try {
-                    evaluator.submitContextAndTask(
-                        configurationSerializer.fromString(request.getContextConfiguration()),
-                        configurationSerializer.fromString(request.getTaskConfiguration()));
-                  } catch (final IOException e) {
-                    throw new RuntimeException("error submitting task and context", e);
-                  }
-                } else if (StringUtils.isNotEmpty(request.getContextConfiguration())) {
-                  // submit context
-                  try {
-                    evaluator.submitContext(configurationSerializer.fromString(request.getContextConfiguration()));
-                  } catch (final IOException e) {
-                    throw new RuntimeException("error submitting context", e);
-                  }
-                } else if (StringUtils.isNotEmpty(request.getTaskConfiguration())) {
-                  // submit task
-                  try {
-                    evaluator.submitTask(configurationSerializer.fromString(request.getTaskConfiguration()));
-                  } catch (final IOException e) {
-                    throw new RuntimeException("error submitting task", e);
-                  }
-                } else {
-                  throw new RuntimeException("Missing check for required evaluator configurations");
-                }
-              } else {
-                if (StringUtils.isNotEmpty(request.getContextConfiguration()) &&
-                    StringUtils.isNotEmpty(request.getTaskConfiguration())) {
-                  // submit context and task
-                  ((AllocatedEvaluatorImpl) evaluator).submitContextAndTask(
-                      request.getEvaluatorConfiguration(),
-                      request.getContextConfiguration(),
-                      request.getTaskConfiguration());
-                } else if (StringUtils.isNotEmpty(request.getContextConfiguration())) {
-                  // submit context
-                  ((AllocatedEvaluatorImpl) evaluator).submitContext(
-                      request.getEvaluatorConfiguration(),
-                      request.getContextConfiguration());
-                } else if (StringUtils.isNotEmpty(request.getTaskConfiguration())) {
-                  // submit task
-                  ((AllocatedEvaluatorImpl) evaluator).submitTask(
-                      request.getEvaluatorConfiguration(),
-                      request.getTaskConfiguration());
-                } else {
-                  throw new RuntimeException("Missing check for required evaluator configurations");
-                }
-              }
+              LOG.log(Level.INFO, "Submitting evaluator with context and service and task");
+              ((AllocatedEvaluatorImpl) evaluator).submitContextAndServiceAndTask(
+                  evaluatorConfiguration,
+                  contextConfiguration,
+                  serviceConfiguration,
+                  taskConfiguration);
             }
+          } else if (contextConfiguration != null) {
+            // submit context
+            if (serviceConfiguration == null) {
+              LOG.log(Level.INFO, "Submitting evaluator with context");
+              ((AllocatedEvaluatorImpl) evaluator).submitContext(evaluatorConfiguration, contextConfiguration);
+            } else {
+              LOG.log(Level.INFO, "Submitting evaluator with context and service");
+              ((AllocatedEvaluatorImpl) evaluator)
+                  .submitContextAndService(evaluatorConfiguration, contextConfiguration, serviceConfiguration);
+            }
+          } else if (taskConfiguration != null) {
+            // submit task
+            if (serviceConfiguration != null) {
+              responseObserver.onError(Status.INTERNAL
+                  .withDescription("Service must be accompanied by a context configuration")
+                  .asRuntimeException());
+            } else {
+              LOG.log(Level.INFO, "Submitting evaluator with task");
+              ((AllocatedEvaluatorImpl) evaluator).submitTask(evaluatorConfiguration, taskConfiguration);
+            }
+          } else {
+            responseObserver.onError(Status.INTERNAL
+                .withDescription("Missing check for required evaluator configurations")
+                .asRuntimeException());
           }
         }
       }
@@ -836,7 +940,9 @@
     public void activeContextOp(
         final ActiveContextRequest request,
         final StreamObserver<Void> responseObserver) {
+      LOG.log(Level.INFO, "Active context operation {0}", request.getOperationCase());
       synchronized (GRPCDriverService.this) {
+        LOG.log(Level.INFO, "i'm in");
         final String contextId = request.getContextId();
         final ActiveContext context = GRPCDriverService.this.activeContextMap.get(contextId);
         if (context == null) {
@@ -930,20 +1036,20 @@
       }
     }
 
-    private void setCLRProcess(
+    private void setEvaluatorProcess(
         final AllocatedEvaluator evaluator,
+        final EvaluatorProcess process,
         final AllocatedEvaluatorRequest.EvaluatorProcessRequest processRequest) {
-      final CLRProcess process = GRPCDriverService.this.clrProcessFactory.newEvaluatorProcess();
       if (processRequest.getMemoryMb() > 0) {
         process.setMemory(processRequest.getMemoryMb());
       }
-      if (processRequest.getConfigurationFileName() != null) {
+      if (StringUtils.isNotEmpty(processRequest.getConfigurationFileName())) {
         process.setConfigurationFileName(processRequest.getConfigurationFileName());
       }
-      if (processRequest.getStandardOut() != null) {
+      if (StringUtils.isNotEmpty(processRequest.getStandardOut())) {
         process.setStandardOut(processRequest.getStandardOut());
       }
-      if (processRequest.getStandardErr() != null) {
+      if (StringUtils.isNotEmpty(processRequest.getStandardErr())) {
         process.setStandardErr(processRequest.getStandardErr());
       }
       evaluator.setProcess(process);
@@ -953,18 +1059,7 @@
         final AllocatedEvaluator evaluator,
         final AllocatedEvaluatorRequest.EvaluatorProcessRequest processRequest) {
       final JVMProcess process = GRPCDriverService.this.jvmProcessFactory.newEvaluatorProcess();
-      if (processRequest.getMemoryMb() > 0) {
-        process.setMemory(processRequest.getMemoryMb());
-      }
-      if (processRequest.getConfigurationFileName() != null) {
-        process.setConfigurationFileName(processRequest.getConfigurationFileName());
-      }
-      if (processRequest.getStandardOut() != null) {
-        process.setStandardOut(processRequest.getStandardOut());
-      }
-      if (processRequest.getStandardErr() != null) {
-        process.setStandardErr(processRequest.getStandardErr());
-      }
+      setEvaluatorProcess(evaluator, process, processRequest);
       if (processRequest.getOptionsCount() > 0) {
         for (final String option : processRequest.getOptionsList()) {
           process.addOption(option);
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverServiceConfigurationProvider.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverServiceConfigurationProvider.java
index 34ea463..77e8711 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverServiceConfigurationProvider.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/driver/service/grpc/GRPCDriverServiceConfigurationProvider.java
@@ -57,6 +57,7 @@
       final ClientProtocol.DriverClientConfiguration driverConfiguration) {
     Configuration driverServiceConfiguration = DriverServiceConfiguration.CONF
         .set(DriverServiceConfiguration.DRIVER_SERVICE_IMPL, GRPCDriverService.class)
+        .set(DriverServiceConfiguration.DRIVER_IDLENESS_SOURCES, GRPCDriverService.class)
         .set(DriverServiceConfiguration.DRIVER_CLIENT_COMMAND, driverConfiguration.getDriverClientLaunchCommand())
         .build();
     return driverConfiguration.getDriverRestartEnable() ?
diff --git a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/examples/hello/HelloREEF.java b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/examples/hello/HelloREEF.java
index 858d6af..bf7774d 100644
--- a/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/examples/hello/HelloREEF.java
+++ b/lang/java/reef-bridge-proto-java/src/main/java/org/apache/reef/bridge/examples/hello/HelloREEF.java
@@ -18,9 +18,9 @@
  */
 package org.apache.reef.bridge.examples.hello;
 
+import org.apache.reef.bridge.client.grpc.JavaClientLauncher;
 import org.apache.reef.bridge.driver.client.DriverClientConfiguration;
 import org.apache.reef.bridge.proto.ClientProtocol;
-import org.apache.reef.bridge.client.DriverServiceLauncher;
 import org.apache.reef.examples.hello.HelloDriver;
 import org.apache.reef.tang.Configuration;
 import org.apache.reef.tang.exceptions.InjectionException;
@@ -61,7 +61,7 @@
         .build());
     builder.addGlobalLibraries(EnvironmentUtils.getClassLocation(HelloDriver.class));
 
-    DriverServiceLauncher.submit(builder.build(), DRIVER_CONFIG);
+    JavaClientLauncher.submit(builder.build(), DRIVER_CONFIG);
     LOG.log(Level.INFO, "REEF job completed");
     ThreadLogger.logThreads(LOG, Level.FINE, "Threads running at the end of HelloREEF:");
   }
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/DotNetProcess.java b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/DotNetProcess.java
new file mode 100644
index 0000000..7b8bcea
--- /dev/null
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/DotNetProcess.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.driver.evaluator;
+
+import org.apache.reef.runtime.common.launch.DotNetLaunchCommandBuilder;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * DotNet evaluator process.
+ */
+public final class DotNetProcess implements EvaluatorProcess {
+  private final DotNetLaunchCommandBuilder commandBuilder = new DotNetLaunchCommandBuilder();
+  private boolean optionSet = false;
+
+  /**
+   * Instantiated via DotNetProcessFactory.
+   */
+  DotNetProcess() {
+  }
+
+  @Override
+  public List<String> getCommandLine() {
+    return commandBuilder
+        .build();
+  }
+
+  @Override
+  public EvaluatorType getType() {
+    return EvaluatorType.DOTNET;
+  }
+
+  @Override
+  public DotNetProcess setMemory(final int megaBytes) {
+    commandBuilder.setMemory(megaBytes);
+    optionSet = true;
+    return this;
+  }
+
+  @Override
+  public boolean isOptionSet() {
+    return optionSet;
+  }
+
+  @Override
+  public DotNetProcess setConfigurationFileName(final String configurationFileName) {
+    commandBuilder.setConfigurationFilePaths(Collections.singletonList(configurationFileName));
+    return this;
+  }
+
+  @Override
+  public DotNetProcess setStandardOut(final String standardOut) {
+    commandBuilder.setStandardOut(standardOut);
+    return this;
+  }
+
+  @Override
+  public DotNetProcess setStandardErr(final String standardErr) {
+    commandBuilder.setStandardErr(standardErr);
+    return this;
+  }
+}
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/DotNetProcessFactory.java b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/DotNetProcessFactory.java
new file mode 100644
index 0000000..1406e64
--- /dev/null
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/DotNetProcessFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.driver.evaluator;
+
+import org.apache.reef.annotations.audience.DriverSide;
+import org.apache.reef.annotations.audience.Private;
+
+import javax.inject.Inject;
+
+/**
+ * Factory to setup new DotNet processes.
+ */
+@Private
+@DriverSide
+public final class DotNetProcessFactory implements EvaluatorProcessFactory<DotNetProcess> {
+  @Inject
+  private DotNetProcessFactory() {
+  }
+
+  @Override
+  public DotNetProcess newEvaluatorProcess() {
+    return new DotNetProcess();
+  }
+}
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorType.java b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorType.java
index 26b61de..4677ed8 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorType.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorType.java
@@ -31,6 +31,10 @@
    */
   CLR,
   /**
+   * Indicates an Evaluator that runs in DOTNET.
+   */
+  DOTNET,
+  /**
    * Indicates an Evaluator whose type hasn't been decided yet. This is common e.g. between Evaluator allocation
    * and launch.
    */
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/client/RunningJobImpl.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/client/RunningJobImpl.java
index 21cfbe5..53bed5c 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/client/RunningJobImpl.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/client/RunningJobImpl.java
@@ -152,9 +152,13 @@
         Optional.<byte[]>empty();
     final Optional<Throwable> cause = this.exceptionCodec.fromBytes(data);
 
-    final String message = cause.isPresent() ?
-        cause.get().getMessage() :
-        "No Message sent by the Job";
+    final String message;
+    if (cause.isPresent() && cause.get().getMessage() != null) {
+      message = cause.get().getMessage();
+    } else {
+      message = "No Message sent by the Job in exception " + cause.get();
+      LOG.log(Level.WARNING, message, cause.get());
+    }
     final Optional<String> description = Optional.of(message);
 
     final FailedJob failedJob = new FailedJob(id, message, description, cause, data);
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/AllocatedEvaluatorImpl.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/AllocatedEvaluatorImpl.java
index c7fab90..2702fc6 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/AllocatedEvaluatorImpl.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/driver/evaluator/AllocatedEvaluatorImpl.java
@@ -246,7 +246,10 @@
     try (final LoggingScope lb = loggingScopeFactory.evaluatorLaunch(this.getId())) {
       final Configuration submissionEvaluatorConfiguration =
           makeEvaluatorConfiguration(
-              contextConfiguration, Optional.of(evaluatorConfiguration), serviceConfiguration, taskConfiguration);
+              contextConfiguration,
+              Optional.ofNullable(evaluatorConfiguration),
+              serviceConfiguration,
+              taskConfiguration);
 
       resourceBuildAndLaunch(submissionEvaluatorConfiguration);
     }
@@ -313,6 +316,8 @@
     final ConfigurationModule evaluatorConfigModule;
     if (this.evaluatorManager.getEvaluatorDescriptor().getProcess() instanceof CLRProcess) {
       evaluatorConfigModule = EvaluatorConfiguration.CONFCLR;
+    } else if (this.evaluatorManager.getEvaluatorDescriptor().getProcess() instanceof DotNetProcess) {
+      evaluatorConfigModule = EvaluatorConfiguration.CONFDOTNET;
     } else {
       evaluatorConfigModule = EvaluatorConfiguration.CONF;
     }
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/evaluator/EvaluatorConfiguration.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/evaluator/EvaluatorConfiguration.java
index 978537d..75b36a9 100644
--- a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/evaluator/EvaluatorConfiguration.java
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/evaluator/EvaluatorConfiguration.java
@@ -68,6 +68,7 @@
    */
   public static final ConfigurationModule CONFCLR = EVALUATOR_CONFIG_MODULE_BUILDER.build();
 
+  public static final ConfigurationModule CONFDOTNET = EVALUATOR_CONFIG_MODULE_BUILDER.build();
   /**
    * This is ConfigurationModule for Java Evaluator.
    */
diff --git a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/DotNetLaunchCommandBuilder.java b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/DotNetLaunchCommandBuilder.java
new file mode 100644
index 0000000..b57f9d0
--- /dev/null
+++ b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/DotNetLaunchCommandBuilder.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.reef.runtime.common.launch;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.reef.util.OSUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A builder for the command line to launch a DotNent Evaluator.
+ */
+public final class DotNetLaunchCommandBuilder implements LaunchCommandBuilder {
+  private static final Logger LOG = Logger.getLogger(DotNetLaunchCommandBuilder.class.getName());
+  private static final String EVALUATOR_DLL_PATH = "reef/global/Org.Apache.REEF.Evaluator.dll";
+  private static final String EVALUATOR_EXE_PATH = "reef/global/Org.Apache.REEF.Evaluator.exe";
+
+  private String standardErrPath = null;
+  private String standardOutPath = null;
+  private List<String> evaluatorConfigurationPaths = new ArrayList<>();
+
+  @Override
+  public List<String> build() {
+    final List<String> result = new LinkedList<>();
+    final File dll = new File(EVALUATOR_DLL_PATH);
+    final File exe = new File(EVALUATOR_EXE_PATH);
+    if (OSUtils.isWindows() && exe.exists()) {
+      LOG.log(Level.WARNING, "Using executable file: {0}", exe.getPath());
+      result.add(exe.getPath());
+    } else if (dll.exists()) {
+      LOG.log(Level.WARNING, "Using dll executable file: {0}", dll.getPath());
+      result.add("dotnet");
+      result.add(dll.getPath());
+    } else {
+      LOG.log(Level.WARNING, "executable file can NOT be found");
+    }
+    result.addAll(evaluatorConfigurationPaths);
+    if (StringUtils.isNotEmpty(this.standardOutPath)) {
+      result.add(">" + this.standardOutPath);
+    }
+    if (StringUtils.isNotEmpty(this.standardErrPath)) {
+      result.add("2>" + this.standardErrPath);
+    }
+    LOG.log(Level.INFO, "Launch Exe: {0}", StringUtils.join(result, ' '));
+    return result;
+  }
+
+  @Override
+  @SuppressWarnings("checkstyle:hiddenfield")
+  public DotNetLaunchCommandBuilder setMemory(final int megaBytes) {
+    return this;
+  }
+
+  @Override
+  public DotNetLaunchCommandBuilder setConfigurationFilePaths(final List<String> configurationFilePaths) {
+    this.evaluatorConfigurationPaths.addAll(configurationFilePaths);
+    return this;
+  }
+
+  @Override
+  public DotNetLaunchCommandBuilder setStandardOut(final String standardOut) {
+    this.standardOutPath = standardOut;
+    return this;
+  }
+
+  @Override
+  public DotNetLaunchCommandBuilder setStandardErr(final String standardErr) {
+    this.standardErrPath = standardErr;
+    return this;
+  }
+}
diff --git a/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/driver/FailBridgeClient.java b/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/driver/FailBridgeClient.java
index 2524dd9..1f05da0 100644
--- a/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/driver/FailBridgeClient.java
+++ b/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/driver/FailBridgeClient.java
@@ -73,7 +73,7 @@
       final int timeOut) throws IOException, InjectionException {
     ClientProtocol.DriverClientConfiguration.Builder builder =
         ClientProtocol.DriverClientConfiguration.newBuilder()
-        .setJobid("Fail_" + failMsgClass.getSimpleName())
+        .setJobid("FailBridge_" + failMsgClass.getSimpleName())
         .addGlobalLibraries(EnvironmentUtils.getClassLocation(FailDriver.class));
     builder.setOperatingSystem(
         OSUtils.isWindows() ?
diff --git a/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/task/BridgeClient.java b/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/task/BridgeClient.java
index 5317a7b..deb8855 100644
--- a/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/task/BridgeClient.java
+++ b/lang/java/reef-tests/src/main/java/org/apache/reef/tests/fail/task/BridgeClient.java
@@ -55,7 +55,7 @@
       final int timeOut) throws IOException, InjectionException {
     ClientProtocol.DriverClientConfiguration.Builder builder =
         ClientProtocol.DriverClientConfiguration.newBuilder()
-            .setJobid("Fail_" + failTaskClass.getSimpleName())
+            .setJobid("FailBridge_" + failTaskClass.getSimpleName())
             .addGlobalLibraries(EnvironmentUtils.getClassLocation(Driver.class));
     builder.setOperatingSystem(
         OSUtils.isWindows() ?
diff --git a/lang/java/reef-tests/src/test/java/org/apache/reef/tests/LocalTestEnvironment.java b/lang/java/reef-tests/src/test/java/org/apache/reef/tests/LocalTestEnvironment.java
index 775b7b1..8b8ba24 100644
--- a/lang/java/reef-tests/src/test/java/org/apache/reef/tests/LocalTestEnvironment.java
+++ b/lang/java/reef-tests/src/test/java/org/apache/reef/tests/LocalTestEnvironment.java
@@ -73,7 +73,7 @@
 
   @Override
   public int getTestTimeout() {
-    return 60000; // 1 min.
+    return 120000; // 2 min.
   }
 
   @Override
diff --git a/lang/java/reef-tests/src/test/java/org/apache/reef/tests/fail/FailBridgeDriverTest.java b/lang/java/reef-tests/src/test/java/org/apache/reef/tests/fail/FailBridgeDriverTest.java
index 217811b..8489295 100644
--- a/lang/java/reef-tests/src/test/java/org/apache/reef/tests/fail/FailBridgeDriverTest.java
+++ b/lang/java/reef-tests/src/test/java/org/apache/reef/tests/fail/FailBridgeDriverTest.java
@@ -70,7 +70,7 @@
       if (OSUtils.isLinux()) {
         TestUtils.assertLauncherFailure(
             FailBridgeClient.runClient(clazz,
-                this.testEnvironment.getRuntimeConfiguration(), this.testEnvironment.getTestTimeout()),
+                this.testEnvironment.getRuntimeConfiguration(), testEnvironment.getTestTimeout()),
             SimulatedDriverFailure.class);
       }
     } catch (IOException e) {
diff --git a/pom.xml b/pom.xml
index 7031b15..3d185e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -312,9 +312,13 @@
                             <exclude>**/*.snk</exclude>
                             <exclude>**/*.opendb</exclude>
                             <exclude>**/*.resx</exclude>
+                            <exclude>**/*.nuspec</exclude>
+                            <exclude>**/*.json</exclude>
+                            <exclude>**/*.pubxml</exclude>
+                            <exclude>**/*.pubxml.user</exclude>
                             <!-- The below are auto generated during the .Net build -->
                             <exclude>**/bin/**</exclude>
-                            <exclude>**/generated/**</exclude>
+                            <exclude>**/generated-sources/**</exclude>
                             <exclude>**/obj/**</exclude>
                             <exclude>**/Release/**</exclude>
                             <exclude>**/Debug/**</exclude>