I am using websocket for showing real time message updates from the server.
My server code snippet is :
My server keeps sending string to my client till the connection is open.
#OnMessage
public void onMessage(String message, #PathParam("client-id") String clientId) {
for (Session client : clients) {
while (client.isOpen()) {
client.getAsyncRemote().sendObject(getStatus());
}
}
}
#OnClose
void onClose(Session peer) {
System.out.println("Removed Peers");
clients.remove(peer);
}
The getStatus() function returns a comma separated string.
My client receives the string(comma separated string) and keeps calling setData() which sets the html element the value of this string.
My client side code is :
var websocket;
var rows;
var vM;
function connect() {
if ($.browser.mozilla) {
webSocket = new MozWebSocket(URL);
} else {
webSocket = new WebSocket(URL);
}
websocket.onopen = function(evnt) {
onOpen(evnt);
};
websocket.onmessage = function(evnt) {
onMessage(evnt);
};
websocket.onerror = function(evnt) {
onError(evnt);
};
websocket.onclose = function() {
console.log("Disconnected");
};
displayMigration();
}
function onOpen(evnt) {
setInterval(function() {
if (websocket.bufferedAmount === 0) {
websocket.send("connect");
}
}, 600);
}
function onMessage(evnt) {
if (typeof evnt.data === "string") {
setData(evnt);
startDataUpdation();
console.log(evnt.data);
}
}
function onError(evnt) {
alert('ERROR: ' + evnt.data);
}
}
Now my websocket executes as required till the time i refresh the screen.Once I refresh it the evnt.data is undefined so onMessage is not getting called even if the connection is open and in readyState=1.
Same behavior is reflected across different browsers. I am using glassfish server 4.0 in Netbeans 7.4 j2ee.
Also after refresh I get this error in the console:
The connection to ws://localhost:8080/WebSocketWorking_2/websocket/client-id was interrupted while the page was loading.
Related
I have a grpc Nodejs server behind a HAproxy and client-streaming rpc java maven.
When I run the java client it return an error:
io.grpc.StatusRuntimeException: UNAVAILABLE: HTTP status code 503
invalid content-type: text/html headers:
Metadata(:status=503,cache-control=no-cache,content-type=text/html)
DATA-----------------------------
503 Service Unavailable No server is available to handle this request.
I already test a rpc client streaming with Nodejs and it worked.
My java client code:
public class App {
public static void main(String[] args) throws InterruptedException {
WebRTCStats stat = WebRTCStats.newBuilder().setUserId("abc").build();
SendWebRTCStats(stat);
}
public static void SendWebRTCStats(WebRTCStats stat) throws InterruptedException {
ManagedChannel channel = ManagedChannelBuilder.forTarget("example.com:443").useTransportSecurity()
.build();
ClientGrpc.ClientStub stub = ClientGrpc.newStub(channel);
StreamObserver<Stat.Status> responseObserver = new StreamObserver<Stat.Status>() {
#Override
public void onNext(Stat.Status status) {
}
#Override
public void onError(Throwable t) {
t.printStackTrace();
}
#Override
public void onCompleted() {
System.out.print("complete");
}
};
StreamObserver<WebRTCStats> requestObserver = stub.sendWebRTCStats(responseObserver);
try {
// Send numPoints points randomly selected from the features list.
requestObserver.onNext(stat);
// Sleep for a bit before sending the next one.
} catch (RuntimeException e) {
// Cancel RPC
requestObserver.onError(e);
throw e;
}
// Mark the end of requests
requestObserver.onCompleted();
// Receiving happens asynchronously
}
}
My NodeJS server:
const PROTO_PATH = './stat.proto';
const grpc = require('grpc');
const protoLoader = require('#grpc/proto-loader');
const fs = require('fs');
const tcp = require('./using.js');
let packageDefinition = protoLoader.loadSync(PROTO_PATH);
let protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const server = new grpc.Server();
server.addService(protoDescriptor.Client.service, {
SendWebRTCStats: async (call, callback) => {
call.on('data', value => {
console.log(value);
tcp.sendLog("test", value);
});
call.on('end', () => {
callback(null, { status: 'success' });
})
},
});
let credentials = grpc.ServerCredentials.createSsl(
fs.readFileSync('ca.cer'), [{
cert_chain: fs.readFileSync('cer.crt'),
private_key: fs.readFileSync('cer_key.key')
}], false);
server.bind("0.0.0.0:443", credentials);
console.log("Server running at 443");
server.start();
Can this problem occurs by different implementations of different libraries of language in GRPC?
so apperently i changed forTarget("example.com) and it worked. I shouldnt specify port for it.
As vertx document mentioned, my java application creates a sockJs bridge to communicate with client via EventBus:
router.mountSubRouter("/eb", sockJSHandler.bridge(options, be -> {
if (be.type() == BridgeEventType.SOCKET_CREATED) {
System.out.println("connection established..." + be.socket().writeHandlerID());
}
if (be.type() == BridgeEventType.RECEIVE) {
System.out.println("received!...");
if (be.socket().uri().contains("login")) {
handleLoginRoute(be);
} else {
String socketId = be.socket().writeHandlerID();
AuthData authData = authDataMap.get(socketId);
if (authData == null)
be.complete(false);
else
be.complete(true);
}
}
}));
and my angular component is like:
private host = 'http://localhost:8080';
ngOnInit(): void {
const self = this;
self.eb = new EventBus(this.host + '/eb');
self.eb.onopen = () => {
// set a handler to receive a message
self.eb.registerHandler('login', (error, message) => {
console.log('received a message: ' );
});
console.log('Send message: ');
self.eb.send('login', {username: 'apple', password: 'red'});
};
self.eb.enableReconnect(true);
}
The connection to the server establishes successfully but vertx server in java is not able to receive any message by the "send" method in client.
I am building a simple prototype based upon the leshan-server-demo included with the repo. I'm attempting to receive updates from objects that have been observed. Packet captures show that the updates are making their way to the server, but I'm receiving no notice of them.
The closest answer I found is from 2015 (How to retrieve updated content on an Observed resource in Leshan?) - but subsequent changes to the Leshan codebase have made the same technique unworkable.
I've tried using the ObservationService to add an ObservationListener, but that only seems to alert me when the Observe has been requested, not when the endpoint sends up changed values.
static private void attachListener(final LeshanServer server) {
System.out.println("Attaching Listener");
server.getObservationService().addListener(new ObservationListener() {
#Override
public void newObservation(Observation observation, Registration registration) {
System.out.println("New Observation");
}
#Override
public void cancelled(Observation observation) {
System.out.println("Observation cancellation");
}
#Override
public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
System.out.println("Observation Response");
}
#Override
public void onError(Observation observation, Registration registration, Exception error) {
System.out.println("Observation Error");
}
});
}
How should I be listening for observed objects on the Leshan server?
You need to handle the onResponse:
From https://github.com/eclipse/leshan/blob/f315c66602b1061175f2441c019b862946d08a55/leshan-server-demo/src/main/java/org/eclipse/leshan/server/demo/servlet/EventServlet.java#L133
#Override
public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
if (LOG.isDebugEnabled()) {
LOG.debug("Received notification from [{}] containing value [{}]", observation.getPath(),
response.getContent().toString());
}
if (registration != null) {
String data = new StringBuilder("{\"ep\":\"").append(registration.getEndpoint()).append("\",\"res\":\"")
.append(observation.getPath().toString()).append("\",\"val\":")
.append(gson.toJson(response.getContent())).append("}").toString();
sendEvent(EVENT_NOTIFICATION, data, registration.getEndpoint());
}
}
The response.getContent() contains the new value. The data json that code builds will look like
{
"ep": "rpitest",
"res": "/3334/0",
"val": {
"id": 0,
"resources": [{
"id": 5704,
"value": 1.7929173707962036
}, {
"id": 5702,
"value": 0.9917597770690918
}, {
"id": 5703,
"value": 154.53704833984375
}]
}
}
If you are using Leshan-server-Demo and if you want to listen to client's notifed value changes from the browser, your frontend side can use eventsource (server sent event) to receive notifications from Leshan-Server Demo.
For example in my angular 7.0 app, I listen to COAP messages changes as below,
// Register Event Source
constructor() {
this.eventsource = new EventSource('server/event?ep=' + this.clientId);
}
// Add listener for COAP messages call back
ngOnInit() {
this.eventsource.addEventListener('COAPLOG', msg => this.coapLogCallback(msg), false);
console.error('Event Source', this.eventsource);
}
// modify coaplogs arrays
coapLogCallback(msg) {
var log = JSON.parse(msg.data);
if (100 < this.coaplogs.length) this.coaplogs.shift();
this.coaplogs.unshift(log);
}
I am trying to create a chat app using Ionic2 (Angular2). I have a Java Server and Ionic 2 Client.
I get the following error:
ORIGINAL EXCEPTION: ReferenceError: io is not defined
Any suggestions please?
Client
import { Component, NgZone } from '#angular/core';
import { Http } from "#angular/http";
declare var io;
//require ('io');
#Component({
templateUrl: 'build/pages/chat/chat.html',
})
export class ChatPage {
private socketHost: string = "http://localhost:3700";
private messages: string[] = [];
private zone: NgZone = null;
private chatBox: string = null;
private socket: any = null;
constructor(http: Http) {
this.messages = [];
this.zone = new NgZone({ enableLongStackTrace: false });
//let url = this.socketHost + "/fetch";
let url = this.socketHost;
http.get(url).subscribe((success) => {
var data = success.json();
for (var i = 0; i < data.length; i++) {
this.messages.push(data[i].message);
}
}, (error) => {
console.log(JSON.stringify(error));
});
this.chatBox = "";
this.socket = io(this.socketHost);
this.socket.on("chat_message", (msg) => {
this.zone.run(() => {
this.messages.push(msg);
});
});
}
send(message) {
if (message && message != "") {
this.socket.emit("chat_message", message);
}
this.chatBox = "";
}
}
HTML
<ion-navbar *navbar>
<ion-title>
Chat
</ion-title>
</ion-navbar>
<ion-content class="home">
<ion-list>
<ion-item *ngFor="let message of messages">{{message}}</ion-item>
</ion-list>
</ion-content>
<ion-footer-bar>
<ion-input>
<input type="text" [(ngModel)]="chatBox" placeholder="Message..." />
<button (click)="send(chatBox)">Send</button>
</ion-input>
</ion-footer-bar>
index.html
<script src="/socket.io/socket.io.js"></script>
Server
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
public class Server {
public static void main(String[] args) {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(3700);
final SocketIOServer server = new SocketIOServer(config);
server.addConnectListener(new ConnectListener() {
#Override
public void onConnect(SocketIOClient client) {
System.out.println("onConnected");
client.sendEvent("message", new Message("", "Welcome to the chat!"));
}
});
server.addDisconnectListener(new DisconnectListener() {
#Override
public void onDisconnect(SocketIOClient client) {
System.out.println("onDisconnected");
}
});
server.addEventListener("send", Message.class, new DataListener<Message>() {
#Override
public void onData(SocketIOClient client, Message data, AckRequest ackSender) throws Exception {
System.out.println("onSend: " + data.toString());
server.getBroadcastOperations().sendEvent("message", data);
}
});
System.out.println("Starting server...");
server.start();
System.out.println("Server started");
}
}
UPDATE
I add the following to index.html, and I don't get any errors any more:
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
But it just hangs. And in Firebug, I can see that the following request is just hanging:
GET http://localhost:3700/
The following is printed in the server console:
onConnected
When the server is not running the following request times out as expected, but when the server is running, the request does return, but with a null response:
GET http://localhost:3700/socket.io/?EIO=3&transport=...LRQn9sx&sid=53081e79-81f3-4fc0-8fb7-17c8673938ca
200 OK
27ms
So it suggests that my server code or the communication between client and server is wrong I think.
Any ideas?
In your Angular app you're listening for and emitting chat_message.
In your Java server you're listening for send and emitting message.
This doesn't add up, does it?
Here is my registerController:
collectionsApp.controller('registerController', function($scope, userService) {
$scope.register = function() {
userService.register($scope.user);
};
});
Here is my serviceController:
collectionsApp.service('userService', function($http) {
return {
login : function(user) {
$http.post('/user/login', user).then(function(data) {
return data;
});
},
register : function(user) {
$http.post('/user/add', user).then(function(data) {
});
}
};
});
When I hit interface button that has data-ng-click="register(user)" registration works just fine BUT when I want to add simple test feedback message responded from backend in data object and edit my registerController like this:
collectionsApp.controller('registerController', function($scope, userService) {
$scope.register = function() {
userService.register($scope.user);
};
userService.register = function(data) {
if (data.status === "success") {
alert("OK");
} else {
alert("NOT OK");
}
};
});
Now I am not able to register new (there are no new user written to db) but I get this "NOT OK" alert every time... Can someone help me fix and understand this mechanism? How to get this status, check it, and send it to view (redirect registered user to new page)?
Thanks in advance...
You are overwriting userService.register in controller so it no longer sends a request to server. What you want to do is to make use of promise pattern, i.g. then callback. Take a look:
collectionsApp.controller('registerController', function($scope, userService) {
$scope.register = function() {
userService.register($scope.user).then(function(data) {
if (data.status === "success") {
alert("OK");
} else {
alert("NOT OK");
}
});
};
});
For this you also need to fix service method, make sure you return promise from it:
register: function(user) {
return $http.post('/user/add', user);
}
To achieve this, don't make changes to your registerController, but change your serviceController
collectionsApp.service('userService', function($http) {
return {
login : function(user) {
$http.post('/user/login', user).then(function(data) {
return data;
});
},
register : function(user) {
$http.post('/user/add', user).then(function(data) {
if (data.status === "success") {
alert("OK");
} else {
alert("NOT OK");
}
});
}
};
});