Search code examples
springspring-bootrxjsangular6server-sent-events

Using RxJs and Angular 5 in order to deal with server-sent events from Spring Boot


I need to update my Angular UI according to data that is emitted from MySQL thorough Spring for every update that happens in MYSQL DB. But on Angular side, I'm not able to fetch the data.

This is my WebController.java on Springboot:

@GetMapping("/summary")
public  SseEmitter Summary(@RequestParam Map<String,String> queryParam,String date, String target) {    
Connection conn = null;
List<Map<String, Object>> listOfMaps = null;
Statement stmt = null;
prodDate = queryParam.get("date").replaceAll("\'", "");
prodTarget = queryParam.get("target").replaceAll("\'", "");

final SseEmitter emitter = new SseEmitter();

try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting to database...To retrive SUMMARY");
conn = DriverManager.getConnection(DB_URL,USER,PASS); 

String query= "SELECT migration_states.state END AS state, migrations.mignum, migrations.projectleader, migrations.productiondate, migrations.installationtiers, "
+ "migrations.targetplatform, migrations.apprelated, migrations.appversion "
+ "FROM (migrations LEFT JOIN migration_states ON migrations.state = migration_states.state_code) "
+ "WHERE migrations.productiondate=? AND migrations.targetplatform=? AND migration_states.state NOT LIKE '%Cancelled%' ";

QueryRunner queryRunner = new QueryRunner();
listOfMaps = queryRunner.query(conn, query, new MapListHandler(), prodDate, prodTarget);               
emitter.send(listOfMaps,MediaType.APPLICATION_JSON);


System.out.println(emitter);
conn.close();
}
catch (SQLException  se) {
se.printStackTrace();
emitter.completeWithError(se);
return emitter;

}catch(Exception e){

e.printStackTrace();
emitter.completeWithError(e);
return emitter;
}finally {
DbUtils.closeQuietly(conn);
}
emitter.complete();
return emitter;
}

Which gives me the following result, when triggered in Postman

http://localhost:8080/api/summary?date=2018-06-06&target=Production 


data:[{"state":"Completed","mignum":146289,"projectleader":"Eric Lok","productiondate":"2018-06-06","installationtiers":"Windows Server","targetplatform":"Production","apprelated":"UPS Pickup Point Web Application","appversion":"2.25"}, 
     {"state":"Completed","mignum":146381,"projectleader":"James Rice","productiondate":"2018-06-06","installationtiers":"Linux Web WL10","targetplatform":"Production","apprelated":"Content Only","appversion":""}, 
     {"state":"Completed","mignum":146461,"projectleader":"Nishith Jani","productiondate":"2018-06-06","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"1801.20"}, 
     {"state":"Completed","mignum":146574,"projectleader":"Nishith Jani","productiondate":"2018-06-06","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"01-00-07-17"}]  

This is my Angular Service call subscribing to WebController

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { map } from 'rxjs/operators';

@Injectable()
export class DashboardDataService {

public baseUrl = 'http://localhost:8080/api';

public headers = new Headers({'Content-Type': 'application/json' });
public options = new RequestOptions({headers: this.headers});  

constructor(private _http: Http) { }

getSummary(_date, _target) {
return this._http.get(this.baseUrl + '/summary?date='+_date+"&target="+_target, this.options).pipe(map((response: Response) => response.json()));
}
}  

This is my component

import { Component, OnInit, OnDestroy } from '@angular/core';
import { DashboardDataService } from '../shared-service/dashboard-data.service';
@Component({
selector: 'app-dashboard-view',
templateUrl: './dashboard-view.component.html',
styleUrls: ['./dashboard-view.component.css']
})
export class DashboardViewComponent implements OnInit, OnDestroy {

constructor(private _dashboardService: DashboardDataService) { }

ngOnInit() {

this._dashboardService.getSummary(this._date, this._target).addEventListener((dashboardataa) => {
this.dashboardataa = dashboardataa;
console.log("this.dashboardata-->", this.dashboardataa);
}, (error) => { console.error('SERVER ERROR'); });
} 
}   

But the issue is that the

console.log("this.dashboardata-->", this.dashboardataa); 

Never gets printed. I'm new to Spring, Ssemitter & Rxjs, so I'mdoing something wrong here. Which I'm not able to figure out. Reading some blogs said me to use addEventListener,but when I try this

this._dashboardService.getSummary(this._date, this._target).addEventListener((dashboardataa) => {
this.dashboardataa = dashboardataa;
console.log("this.dashboardata-->", this.dashboardataa); }  

I get error saying

error TS2339: Property 'addEventListener' does not exist on type 'Observable'.

Can anyone help me how to write correct code on Angular side, to get the json data, which will emiited, when the update happens on Server side.


Solution

  • You should use just Observables:

    getSummary(_date, _target) : Observable<any> {
        return this._http.get(this.baseUrl + '/summary?date='+_date+"&target="+_target, 
        this.options);
    }
    

    and in your component subscribe to it:

    this._dashboardService.getSummary(this._date, this._target).subscribe((dashboardataa) => {
       this.dashboardataa = dashboardataa;
       console.log("this.dashboardata-->", this.dashboardataa);
    
       }, (error) => { console.error('SERVER ERROR'); });
    } 
    }