diff --git a/src/app/job/job.component.html b/src/app/job/job.component.html
index b708c3c8cac304add0491076dde2287f5ece35cc..e11bec3f7edb4dec5ed7af8e93b2bbaa1a7d4589 100644
--- a/src/app/job/job.component.html
+++ b/src/app/job/job.component.html
@@ -1,6 +1,6 @@
 <mat-card>
   <mat-card-title>{{ jobdata.name }}</mat-card-title>
-  <div *ngIf="(jobdata.connectionState === undefined || jobdata.connectionState == 0)">
+  <div *ngIf="jobdata.connectionState == 0">
   <div gdAreas="name name name name|
                 status resources space buttons"
        gdColumns="20% 60% auto 20%">
diff --git a/src/app/job/job.component.ts b/src/app/job/job.component.ts
index c3b76f49d53fe3b0cb0823002aa3451170f8829a..55a6767db3700c2c33d1c1936efb02a7b1de1312 100644
--- a/src/app/job/job.component.ts
+++ b/src/app/job/job.component.ts
@@ -19,6 +19,7 @@ export class JobComponent implements OnInit {
   constructor(private tesService: TesService, private strudelAppsService: StrudelappsService) {
 
 
+
 }
 
   ngOnInit() {
diff --git a/src/app/launcher/launcher.component.html b/src/app/launcher/launcher.component.html
index 1e6dfdcbb1f1e4b3d77dac395e846bf7c42156e4..768bba7e6f8e208fa6bd5f232d39b56e3aa19f5a 100644
--- a/src/app/launcher/launcher.component.html
+++ b/src/app/launcher/launcher.component.html
@@ -41,11 +41,17 @@
             Advanced Options
         </mat-expansion-panel-header>
         Select an API server
-        <mat-select (selectionChange)="tesService.apiserver.next($event.value)" [value]="tesService.apiserver|async">
+        <!--(selectionChange)="tesService.setApiServer($event.value)" [compareWith]="tesService.compareServers"-->
+        <mat-select [ngModel]="selectedApiServer" (selectionChange)="tesService.setApiServer($event.value)">
             <mat-option *ngFor="let apis of tesService.apiservers|async" [value]="apis">
                 {{ apis.name }}
             </mat-option>
         </mat-select>
+        <!--<mat-select [ngModel]="tesService.apiserver | async" (ngModelChange)="tesService.setApiServer($event)">
+            <mat-option *ngFor="let apis of tesService.apiservers|async" [value]="apis">
+                {{ apis.name }}
+            </mat-option>
+        </mat-select>-->
     </mat-expansion-panel>
 	</mat-accordion>
 </mat-sidenav>
diff --git a/src/app/launcher/launcher.component.ts b/src/app/launcher/launcher.component.ts
index 89ab94026a4b690df50940531dbb4b31f20efa18..608faa87feaf9ccf282957277c5cebfc438a40c0 100644
--- a/src/app/launcher/launcher.component.ts
+++ b/src/app/launcher/launcher.component.ts
@@ -41,6 +41,7 @@ export class LauncherComponent implements OnInit {
   public sshauthzservers: SshAuthzServer[];
   private launchwindow: any;
   private launchwindowWatcher: any;
+  public selectedApiServer: any;
 
   constructor( public dialog: MatDialog,
                 public tesService: TesService,
@@ -49,6 +50,7 @@ export class LauncherComponent implements OnInit {
                 ) {
     this.authService.sshAuthzServers.subscribe(o => {this.sshauthzservers = o});
     this.identitySubject = new BehaviorSubject(undefined);
+    this.tesService.apiserver.subscribe((s) => this.selectedApiServer = s);
   }
 
   ngOnInit() {
@@ -56,6 +58,7 @@ export class LauncherComponent implements OnInit {
     setTimeout( () => this.authService.updateAgentContents() )
   }
 
+
   //updateIdentities(identities) {
   //  this.identities = identities;
   //  console.log(this.identities);
diff --git a/src/app/tes.service.ts b/src/app/tes.service.ts
index 3466aefc240919b392d9fd4d321e2c8344aa2769..662bf7ad58b34b884492e20f351b6cc093a9fdc5 100644
--- a/src/app/tes.service.ts
+++ b/src/app/tes.service.ts
@@ -32,8 +32,10 @@ Its also responsible for querying a compute site for running jobs */
   providedIn: 'root',
 })
 export class TesService {
-public Base=environment.tesurl;
-private twsproxy = environment.twsurl;
+public Base: string;
+//public Base=environment.tesurl;
+//private twsproxy = environment.twsurl;
+private twsproxy: string;
 // public Base='http://localhost:5000';
 public statusMsg: BehaviorSubject<any>;
 public jobs: any[];
@@ -58,9 +60,8 @@ public apiservers: BehaviorSubject<APIServer[]>;
     this.busy = new BehaviorSubject<boolean>(false);
     // this.joblist = new BehaviorSubject<{[id: string]: Job[]}>({});
     this.joblist = new BehaviorSubject<Job[]>([]);
-      this.apiserver = new BehaviorSubject<APIServer>(undefined);
+      this.apiserver = new BehaviorSubject<APIServer>(null);
     this.apiservers = new BehaviorSubject<APIServer[]>([]);
-    this.apiserver.subscribe((r)=>this.onApiServerChange(r));
 
     this.timerSubscription = null;
     this.appwindowWatcher = null;
@@ -73,14 +74,56 @@ public setStatusMsg(statusMsg: BehaviorSubject<any>) {
   this.statusMsg = statusMsg;
 }
 
-private onApiServerChange(r) {
+public compareServer(a: APIServer, b: APIServer) {
+    if (a.name == b.name) {
+        return true;
+    }
+    return false;
+}
+
+private loadLastApiServer() {
+    var lastserver: APIServer;
+    try {
+        console.log('loading api server from local storage');
+        lastserver = JSON.parse(localStorage.getItem('apiserver'));
+    } catch {
+        lastserver = undefined;
+    }
+    // If we got a value for the last server used, we need to search the list of available servers for a match
+    if (lastserver != undefined) {
+        for (let s of this.apiservers.value) {
+            if (lastserver.name == s.name) {
+                this.apiserver.next(s);
+            }
+        }
+    }
+    // If we didn't get a match, we'll just pick the first available server
+    if (this.apiserver.value == null) {
+        if (this.apiservers.value.length > 0) {
+            this.apiserver.next(this.apiservers.value[0]);
+        } else {
+            // If there are NO available backed servers ... well we shouldn't get here.
+            // In the future if we start detecting backends as down for maintainnce it might happen
+            this.statusMsg.next("There was an error selecting a backend API server. Please try reloading");
+            return;
+        }
+    }
     this.Base = this.apiserver.value.tes;
     this.twsproxy = this.apiserver.value.tws;
+    console.log('load succeeded');
+}
+private saveLastApiServer(s: APIServer) {
+    console.log('saving api server value to local storage')
+    localStorage.setItem('apiserver', JSON.stringify(s));
 }
 
  setApiServer(server: APIServer) {
      console.log('calling setAPIServer');
      this.apiserver.next(server);
+     console.log(this.apiserver);
+     this.Base = this.apiserver.value.tes;
+     this.twsproxy = this.apiserver.value.tws;
+     this.saveLastApiServer(this.apiserver.value)
  }
 
  getAPIServers() {
@@ -92,7 +135,7 @@ private onApiServerChange(r) {
 
  private updateAPIServers(resp) {
      this.apiservers.next(<APIServer[]>resp);
-     this.apiserver.next(this.apiservers.value[0]);
+     this.loadLastApiServer();
  }
 
 
@@ -110,17 +153,52 @@ private onApiServerChange(r) {
    return params.toString();
  }
 
+
  updateJoblist(resp, identity: Identity) {
-   let joblist = <Job[]>resp;
-   let alljobs = this.joblist.value;
-   let i = 0;
-   for (let j of joblist) {
-     j.app = this.strudelappsService.getApp(j.name,identity.site.appCatalog.value);
-     j.identity = identity;
+     // resp contains a javascript represnetiation of a list of jobs
+     // We want to update the joblist BUT we don't want to create new Job objects
+     // instead we want to reuse existing job objects removing any which are no longer valid
+     // and adding any new ones. We also want the list sorted from largest jobid to smallest (oldest job)
+     // The sort is lexographic since sometimes jobids are a string rather than a number
+   
+   var joblist: Job[] = []
+   var jobquery: Job[] = <Job[]>resp;
+   var lastjoblist: Job[] = this.joblist.value;
+   var qjobids: any[] = [];
+   var jobids: any[] = [];
+   var j: Job
+
+   for (j of jobquery) {
+       qjobids.push(j.jobid);
+   }
+   for (j of lastjoblist) {
+       if (qjobids.indexOf(j.jobid) != -1) {
+           if (jobids.indexOf(j.jobid) == -1) {
+               joblist.push(j);
+               jobids.push(j.jobid);
+           }
+       }
+   }
+   for (j of jobquery) {
+       if (jobids.indexOf(j.jobid) == -1) {
+           joblist.push(j);
+           jobids.push(j.jobid);
+       }
+   }
+       
+   for (j of joblist) {
+     if (j.app === undefined) {
+       j.app = this.strudelappsService.getApp(j.name,identity.site.appCatalog.value);
+     }
+     if (j.identity == undefined) {
+        j.identity = identity;
+     }
+     if (j.connectionState == undefined) {
+         j.connectionState = 0;
+     }
    }
+   joblist = joblist.sort((a,b) =>  (a.jobid < b.jobid)? 1:-1);
    this.joblist.next(joblist)
-   // alljobs[identity.repr()] = joblist;
-   // this.joblist.next(alljobs);
  }
 
  private getBatchInterfaceError(error: any) {
@@ -258,12 +336,17 @@ private onApiServerChange(r) {
    let batchhost = job.batch_host;
    let params = new URLSearchParams;
    let headers = new HttpHeaders();
+   console.log('setting Connectionstate 2');
    job.connectionState = 2;
+
+     //    let sleepDuration = 20;
+     //var now = new Date().getTime();
+     //while(new Date().getTime() < now + sleepDuration){ /* do nothing */ }
+
    let options = { headers: headers, withCredentials: true};
    params.set('cmd',JSON.stringify(job.app.paramscmd));
    let paramstr = params.toString();
    this.http.post<string>(this.Base+'/createtunnel/'+username+'/'+loginhost+'/'+batchhost+'?'+paramstr, job.appinst, options)
-                // .pipe(catchError(this.handleError))
                 .subscribe(() =>  { this.getAppUrl(job) } )
  }
 
@@ -291,6 +374,14 @@ private onApiServerChange(r) {
      console.log('window loc is ',windowloc);
    // let windowloc = this.router.config
    this.appwindow = window.open(windowloc);
+   console.log('check if the appwindow is valid',this.appwindow);
+     if (this.appwindow == null) {
+         this.statusMsg.next('It looks like a window failed to open. Please check your popup blocker settings (Strudel 2 needs to be able to open a window to your application');
+         return;
+     }
+     if (this.appwindow.closed) {
+         console.log('appwindow failed to open');
+     }
    if (!(this.appwindowWatcher === null)) {
      this.appwindowWatcher.unsubscribe()
    }