I'm trying to learn websocket. I started sending simple string between peers and everything was fine. Now I'm trying to send Object to my javascript client but the onmessage function never fires. Here is the code:
@ServerEndpoint(value = "/event/{id}",
encoders={PositionJSONEncoder.class},
decoders={PositionJSONDecoder.class}
)
public class SocketManager {
private static ConcurrentHashMap<String, Session> users = new ConcurrentHashMap<String, Session>();
@OnMessage
public void onMessage(Position position, @PathParam("id") String id, Session session) {
log.info("user "+id+", "+position.toString());
try {
for(Entry<String, Session> entry : users.entrySet()) {
if(!entry.getKey().equals(position.getUserID()) && entry.getValue().isOpen()) {
entry.getValue().getBasicRemote().sendObject(position);
}
}
} catch (EncodeException ee) {
log.error(ee);
} catch (IOException ioe) {
log.error(ioe);
}
}
}
public class PositionJSONEncoder implements Encoder.Text<Position>{
private Gson gson = new Gson();
public void destroy() {}
public void init(EndpointConfig arg0) {}
public String encode(Position arg0) throws EncodeException {
return gson.toJson(arg0);
}
}
app.factory('socket', function() {
var service = {};
service.ws = {};
service.connect = function(userID) {
this.ws = new WebSocket("ws://localhost:8080/event/"+userID);
};
service.disconnect = function() {
if(this.ws != undefined && this.ws != null) {
this.ws.onclose();
}
};
service.ws.onopen = function() {
// TODO
};
service.ws.onmessage = function(msg) {
try {
alert('roba: '+JSON.parse(msg.data));
} catch(err) {
alert(err.message);
}
};
service.ws.onclose = function() {
// TODO
};
service.ws.onerror = function(evt) {
alert(evt.data);
};
return service;
});
public class Position {
private String userID;
private Float lat;
private Float lng;
public Position() {}
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public Float getLat() {
return lat;
}
public void setLat(Float lat) {
this.lat = lat;
}
public Float getLng() {
return lng;
}
public void setLng(Float lng) {
this.lng = lng;
}
@Override
public String toString() {
return userID+"["+"lat: "+lat+", "+"lng: "+lng+"]";
}
}
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!-- GSON JSON serializer -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
The server gets the JSON object from the client correctly, but when it sends some Position object back the client, the onmessage
function won't fire. I can see the Encoder is working as it returns strings like this:
{"userID":"bob","lat":2.0,"lng":2.0}
I see the websocket carry the messages:
but my javascript onmessage
function always stay silent. I also implemented an onerror
function but I can't get any feedback from it too. I'm using wildfly-8.0.0.Final.
Update: I implement a java websocket client. This client receive websocket frame sent by the server. Is my AngularJS client wrong?
I found what was wrong. In my javascript client I assigned a function to an undefined object. Here:
service.ws.onmessage = function(msg) {
try {
alert('roba: '+JSON.parse(msg.data));
} catch(err) {
alert(err.message);
}
};
service.ws.onmessage
was undefined, that's why onmessage
function never fire. I change my angular factory in this way:
app.factory('socket', function() {
var service = {};
service.ws = {};
service.connect = function(userID) {
this.ws = new WebSocket("ws://localhost:8080/event/"+userID);
this.ws.onmessage = function(msg) {
try {
alert('roba: '+JSON.parse(msg.data).lat+' :: '+JSON.parse(msg.data).lng);
} catch(err) {
alert(err.message);
}
};
this.ws.onerror = function(evt) {
alert('error: '+evt.data);
};
};
service.disconnect = function() {
if(this.ws != undefined && this.ws != null) {
this.ws.onclose();
}
};
return service;
});