Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Workaound: ng2-stompjs over SockJS in Angular 6 #70

Open
srjovanovic opened this issue May 10, 2018 · 39 comments
Open

Workaound: ng2-stompjs over SockJS in Angular 6 #70

srjovanovic opened this issue May 10, 2018 · 39 comments

Comments

@srjovanovic
Copy link

srjovanovic commented May 10, 2018

Based on your setup, you might get error similar to following:

browser-crypto.js:3 Uncaught ReferenceError: global is not defined
    at Object../node_modules/sockjs-client/lib/utils/browser-crypto.js (browser-crypto.js:3)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/utils/random.js (random.js:4)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/utils/event.js (event.js:3)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/transport/websocket.js (websocket.js:3)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/transport-list.js (transport-list.js:5)
    at __webpack_require__ (bootstrap:81)

The actual issue can be solved by SockJs team, see: #70 (comment).

Please see #70 (comment) and #70 (comment) for possible workarounds.

@srjovanovic srjovanovic changed the title ng2-stompjs over SockJS ng2-stompjs over SockJS? May 10, 2018
@kum-deepak
Copy link
Member

@srjovanovic
Copy link
Author

Thank you very much.

@wsloth
Copy link

wsloth commented May 10, 2018

Has this been confirmed to work with Angular 6? When following the documentation example I get a runtime error whilst connecting to the SockJS endpoint:

browser-crypto.js:3 Uncaught ReferenceError: global is not defined
    at Object../node_modules/sockjs-client/lib/utils/browser-crypto.js (browser-crypto.js:3)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/utils/random.js (random.js:4)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/utils/event.js (event.js:3)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/transport/websocket.js (websocket.js:3)
    at __webpack_require__ (bootstrap:81)
    at Object../node_modules/sockjs-client/lib/transport-list.js (transport-list.js:5)
    at __webpack_require__ (bootstrap:81)

@kum-deepak
Copy link
Member

The Angular 6 version of this library has only been released yesterday, so, I am doubtful if anyone has used in production at all.

I can be reasonably sure that no one would have used it with SockJS and Angular 6 by now 😄

Before I dig deeper, are you using 6.0.0 of this library (released yesterday)?

@wsloth
Copy link

wsloth commented May 10, 2018

Yes, I am! I am trying to use it for a prototype application where I have no control over how the backend works, but it seems it's not functioning with Angular 6 sadly.

If it's too much work I'll just downgrade to Angular 5, but it'd be nice to use all the new features from 6 while building something new.

@kum-deepak
Copy link
Member

I can confirm that I am able to reproduce the issue. It seems to be reported here: sockjs/sockjs-client#401

Not sure it would be an easy solution till the underlying thing gets fixed.

@wsloth if your underlying broker supports Websockets (which in all likelihood it should), you can use that instead of going through the SockJS emulation layer. Any particular reason you need SockJS?

@kum-deepak kum-deepak changed the title ng2-stompjs over SockJS? ng2-stompjs over SockJS in Angular 6? May 10, 2018
@wsloth
Copy link

wsloth commented May 10, 2018

I see, it doesn't seem like an easy fix. I'm working on something of a code exercise where I have full control over the frontend, but none over the backend, so that is a bit of a shame.

I'll see if I can downgrade to Angular 5, or for the sake of making something beautiful ditch the SockJS protocol.

@kum-deepak
Copy link
Member

Just curious what advantage are you getting with SockJS in comparison to standard WebSocket?

@wsloth
Copy link

wsloth commented May 10, 2018

Nothing really, it's just that the backend has already been made and SockJS was decided for the messaging protocol. If it were up to me, I'd be using standard WebSockets 😉

@kum-deepak
Copy link
Member

I am always getting surprised people choosing SockJS instead of WebSockets which would internally use WebSockets anyway. Using SockJS does limit some of the functionality of this library as well.

So far most number of tickets on this project relate to SockJS issues 😄

@srjovanovic
Copy link
Author

I can confirm that ng2-stompjs over SockJS is working with Angular 6.
But I'm having problems with subscribe, after reconnecting subscription doubles.

@kum-deepak
Copy link
Member

Not sure if that would work - in your index.html file, in the header try adding the following:

  <script type="application/javascript">
    var global = window;
  </script>

I am unable to test it myself though

@kum-deepak
Copy link
Member

@srjovanovic your issue may be linked to something else. Will you be able to share a sample repository that shows StompJS working with Angular6 and also your issue.

@srjovanovic
Copy link
Author

@kum-deepak I've made more test with Angular 5, and I can confirm that my issue has nothing with Angular 6.
So ng2-stompjs and SockJS are working for me on Angular 6.

@aceleghin
Copy link

After upgrade angular and ng2-stompjs I have the same error:

Uncaught ReferenceError: global is not defined
at Object../node_modules/sockjs-client/lib/utils/browser-crypto.js (browser-crypto.js:3)
at webpack_require (bootstrap:81)
at Object../node_modules/sockjs-client/lib/utils/random.js (random.js:4)
at webpack_require (bootstrap:81)
at Object../node_modules/sockjs-client/lib/utils/event.js (event.js:3)
at webpack_require (bootstrap:81)
at Object../node_modules/sockjs-client/lib/transport/websocket.js (websocket.js:3)
at webpack_require (bootstrap:81)
at Object../node_modules/sockjs-client/lib/transport-list.js (transport-list.js:5)
at webpack_require (bootstrap:81)

And following your link https://stomp-js.github.io/ng2-stompjs/additional-documentation/sock-js.html
I see a old library sockjs-client...

@aceleghin
Copy link

@srjovanovic Can you show me an example of stompjs working with angular 6? or maybe your code?

@srjovanovic
Copy link
Author

srjovanovic commented May 29, 2018

@lippomano

Service:
`
import {Injectable} from "@angular/core";
import {ENV} from "@app/environments";
import {StompConfig, StompRService, StompState} from "@stomp/ng2-stompjs";
import {Message} from "@stomp/stompjs";
import {Platform} from "ionic-angular";
import {Observable, Subscription} from "rxjs/Rx";
import * as SockJS from "sockjs-client";
import {Auth0Service} from "../auth-service/auth0-service";
import {NotificationsProvider} from "../notifications-service/notifications-service";

@Injectable()
export class SocketStompProvider {
public stompConfig: StompConfig;
public stompEndpoint: string = "endpointName";
public stompStatus: string;
public stompStatusId: number;
public messages: Observable;
private readonly showStompStatusId: boolean;
private reconnectEnabled: boolean;
private readonly reconnectTimeout: number;
private subscription: Subscription;
private serverSocket;
private topic: string = "/queue/messages";
private loggedProfileDetails;
private accountToken: string;
private bearerToken: string;
private readonly debugService: boolean = false;

constructor(private stompService: StompRService,
            private notificationsService: NotificationsProvider,
            private oAuthService: OAuthService,
            private platform: Platform) {
    this.debugService = (ENV.LOG_LEVEL !== "0");
    if (this.debugService) {
        this.stateStompService();
    }
    this.stompStatus = "STARTING";
    this.reconnectTimeout = 15000;
    this.reconnectEnabled = false;
    this.showStompStatusId = this.debugService;
}

public reinitializeServiceSocketConnection() {
    this.initServiceSocketConnection(this.stompEndpoint);
}

public socketProvider(serverUrl) {
    return new SockJS(serverUrl);
}

public unsubscribeStompTopic() {
    if (this.subscription) {
        this.subscription.unsubscribe();
        this.subscription = null;
        this.messages = null;
    }
}

public disconnectSocketFromService() {
    if (this.stompStatus === "CONNECTED") {
        this.reconnectEnabled = false;
        this.unsubscribeStompTopic();
        this.stompService.disconnect();
    }
}

public setStompServiceConfiguration() {
    this.stompConfig = {
        debug: this.debugService,
        headers: {},
        heartbeat_in: 30000,
        heartbeat_out: 30000,
        reconnect_delay: this.reconnectTimeout,
        url: this.serverSocket,
    };
}

public getEndpointAuthorizationHeader(): string {
    let authorizeEndpoint = null;
    this.loadAuthTokensFromStorage();
    if (this.accountToken) {
        authorizeEndpoint = "?" +
            "Authorization=" + this.bearerToken +
            "&Account-Info=" + this.accountToken;
    }
    return authorizeEndpoint;
}

public stateStompService() {
    this.stompService.state
        .map((state: number) => StompState[state])
        .subscribe((status: string) => {
            this.stompStatus = status;
            if (this.reconnectEnabled && this.stompStatus === "CLOSED" &&
                this.notificationsService.notificationsEnabled) {
                this.oAuthService.getNewAccessTokenNotification();
                this.reinitializeServiceSocketConnection();
            }
            if (this.showStompStatusId) {
                switch (status) {
                    case "CLOSED": {
                        this.stompStatusId = 0;
                        break;
                    }
                    case "TRYING": {
                        this.stompStatusId = 1;
                        break;
                    }
                    case "CONNECTED": {
                        this.stompStatusId = 2;
                        break;
                    }
                    case "DISCONNECTING": {
                        this.stompStatusId = 3;
                        break;
                    }

                }
            }
        });
}

public onSendMessage(messageText) {
    this.stompService.publish(this.topic, messageText);
}

private initServiceSocketConnection(stompEndpoint: string) {
    if (this.notificationsService.notificationsEnabled) {
        const authorizationHeader = this.getEndpointAuthorizationHeader();
        if (authorizationHeader) {
            this.serverSocket = this.socketProvider(ENV.URL + stompEndpoint + authorizationHeader);
            this.setStompServiceConfiguration();
            if (!this.subscription) {
                this.subscribeStompTopic();
            }
            if (this.stompStatus !== "CONNECTED" && this.stompStatus !== "TRYING") {
                this.connectSocketToService();
            }
            this.notificationsService.getNotificationsHistory();
        }
    }
}

private subscribeStompTopic() {
    if (!this.subscription) {
        this.messages = this.stompService.subscribe(this.topic);
        this.subscription = this.messages.subscribe(this.onNewMessage);
    }
}

private onNewMessage = (message: Message) => {
    this.notificationsService.processMessage(JSON.parse(message.body));
};

private loadAuthTokensFromStorage() {
    this.loggedProfileDetails = JSON.parse(localStorage.getItem("profile-cm"));
    if (this.loggedProfileDetails) {
        this.accountToken = this.loggedProfileDetails.accountInfoToken;
    }
    this.bearerToken = "Bearer " + localStorage.getItem("access_token");
}

private connectSocketToService() {
    this.stompService.config = this.stompConfig;
    this.stompService.initAndConnect();
    this.reconnectEnabled = true;
}

}`

@srjovanovic
Copy link
Author

Relevant package versions:
angular/common: 6.0.2
angular/compiler: 6.0.2
angular/compiler-cli: 6.0.2
angular/core: 6.0.2
angular/forms: 6.0.2
angular/http: 6.0.2
angular/platform-browser: 6.0.2
angular/platform-browser-dynamic: 6.0.2
stomp/ng2-stompjs: 4.0.0
rxjs: 6.1.0
rxjs-compat: 6.1.0
sockjs-client: 1.1.4
tsickle: 0.28.0
typescript: 2.7.2
webpack: 4.8.3
zone.js: 0.8.26

@aceleghin
Copy link

@srjovanovic I have a configuration like you but if I use new SockJS(sockUrl); in config for the stomp url I have the errors posted in the previous comment.
Any idea why I have these errors?

P.s. If I use for example an url like ws://127.0.0.1:15674/ws without initializing a new SockJS it seems working but I need to initialize sockJS with an url like http:...

@srjovanovic
Copy link
Author

srjovanovic commented May 30, 2018

As you can see from my code, I'm using newSockJS(serverUrl), for dev env I use serverUrl=https://localhost:9000/

@aceleghin
Copy link

@srjovanovic @kum-deepak just tried with the example in angular 6 ng6-example and I follow this way with sockJS And I still have the same error, I can't understand how you don't have error

@kum-deepak
Copy link
Member

kum-deepak commented May 30, 2018

It is definitely not working for me 😃. Copying from my earlier comments:

The underlying issue is in SockJS and the way Angular 6 is trying to bundle the code. It is reported here: sockjs/sockjs-client#401. Not sure it would be an easy solution till the underlying thing gets fixed.

Not sure if it would work. In your index.html file, in the header try adding the following:

  <script type="application/javascript">
    var global = window;
  </script>

Be warned 😄, test your application, this may have unintended side effects.

A better solution, if you can, switch to standard Websockets.

@aceleghin
Copy link

@kum-deepak thanks for your feedback, what type of side effects?

@kum-deepak
Copy link
Member

Generally global is used by NodeJS, it is not used by browsers. SockJS code is expecting global to have certain methods, in case of browsers those methods are attached to window. So, the above snippet is likely to provide a workaround.

Now the risk part, global might be used by some other libraries conditionally. Whatever I can imagine, it should not have negative impacts. Only way to be sure would be to test your application with this added (I mean the entire application).

@kum-deepak kum-deepak reopened this May 30, 2018
@aceleghin
Copy link

It's working, but I have to test it more accurately.

@satyendra-123
Copy link

Getting the below error in browser after updating to angular 6
browser-crypto.js:3 Uncaught ReferenceError: global is not defined
at Object../node_modules/sockjs-client/lib/utils/browser-crypto.js (browser-crypto.js:3)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/utils/random.js (random.js:4)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/utils/event.js (event.js:3)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/transport/websocket.js (websocket.js:3)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/transport-list.js (transport-list.js:5)
at webpack_require (bootstrap:76)

@kum-deepak thanks for your feedback, It does the workaround for me. Is there anything with the compatible dependency for angular 6 to fix it ?

@kum-deepak
Copy link
Member

@satyendra-123 unfortunately the issue can only be fixed either by Angular team or by SockJS team.

@tnobody
Copy link

tnobody commented Jun 14, 2018

I fixed it for with adding this line:

(window as any).global = window;

to angular-clis polyfill.ts file. right now couldn't see any sideeffects

@kum-deepak kum-deepak changed the title ng2-stompjs over SockJS in Angular 6? Workaound ng2-stompjs over SockJS in Angular 6 Jul 12, 2018
@kum-deepak kum-deepak changed the title Workaound ng2-stompjs over SockJS in Angular 6 Workaound: ng2-stompjs over SockJS in Angular 6 Jul 12, 2018
@tamama
Copy link

tamama commented Jul 23, 2018

@kum-deepak Your workaround-fix works for me for raw SockJS connection:

<script type="application/javascript"> var global = window; </script>

I will next try using the stomp protocol over it, and will update you soon.

FYI:
[vagrant@london-node-230 ~]$ ng --version

 _                      _                 ____ _     ___
/ \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|

/ △ \ | '_ \ / | | | | |/ _ | '__| | | | | | |
/ ___ | | | | (
| | || | | (| | | | || | | |
// __| ||_, |_,||_,|| _|||
|___/

Angular CLI: 6.0.7
Node: 8.11.2
OS: linux x64
Angular:
...

Package Version

@angular-devkit/architect 0.6.7
@angular-devkit/core 0.6.7
@angular-devkit/schematics 0.6.7
@schematics/angular 0.6.7
@schematics/update 0.6.7
rxjs 6.2.0
typescript 2.7.2

[vagrant@london-node-230 ~]$

@tamama
Copy link

tamama commented Jul 23, 2018

@kum-deepak Your workaround-fix works.

<script type="application/javascript"> var global = window; </script>

@joaquintoral
Copy link

image

I am getting undefined here. Why is that?

@kum-deepak
Copy link
Member

kum-deepak commented Oct 20, 2018

Typically the CONNECTED frame (in response to CONNECT frame from the client) from broker returns a server header. If a broker does not return this header it will show undefined as above.

Which broker are you using?

This is not an error, this value is not used other than reporting it in log. It should not impact your usage.

@bhabanipattanayak
Copy link

@kum-deepak
Hi Deepak,

Is there any way now to convert the protocol to http instead of wss. I am getting "global is not defined"

@kum-deepak
Copy link
Member

If the URL supported by your broker starts with ws: or wss:, it supports WebSockets. In that case you do not need SockJS.

You can not interchange wss: and http: - both are different protocols.

If the broker only supports http, then follow #70 (comment) as a workaround for "global is not defined"

@goldy12103
Copy link

goldy12103 commented Mar 22, 2021

Getting the below error in browser in angular 9
browser-crypto.js:3 Uncaught ReferenceError: global is not defined
at Object../node_modules/sockjs-client/lib/utils/browser-crypto.js (browser-crypto.js:3)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/utils/random.js (random.js:4)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/utils/event.js (event.js:3)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/transport/websocket.js (websocket.js:3)
at webpack_require (bootstrap:76)
at Object../node_modules/sockjs-client/lib/transport-list.js (transport-list.js:5)
at webpack_require (bootstrap:76)

@kum-deepak seems like still the error is not fixed by angular or sockJS team , is there any better solution without using this (window as any).global = window;

@kum-deepak
Copy link
Member

@goldy12103, this is not fixable by the Angular team. It would need fixing by the SockJS team.

@goldy12103
Copy link

@kum-deepak

Is there any better solution without using this (window as any).global = window; ???

@kum-deepak
Copy link
Member

Please scan this thread. There are other solutions, however, all of those lead to the same thing.

@goldy12103
Copy link

Thanks Anyway !!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants