This code is taken from AthmospherePushConnection.java of the flow server. I’m having issues with the long polling transport. In order to track the issue down, I have a question regarding the part “for(;;)” of the message. What’s the purpose of this “for(;;)” ?
/**
* Pushes pending state changes and client RPC calls to the client. If
* {@code isConnected()} is false, defers the push until a connection is
* established.
*
* @param async
* True if this push asynchronously originates from the server,
* false if it is a response to a client request.
*/
public void push(boolean async) {
if (!isConnected()) {
if (async && state != State.RESPONSE_PENDING) {
state = State.PUSH_PENDING;
} else {
state = State.RESPONSE_PENDING;
}
} else {
try {
JsonObject response = new UidlWriter().createUidl(getUI(),
async);
sendMessage("for(;;);[" + response.toJson() + "]
");
} catch (Exception e) {
throw new RuntimeException("Push failed", e);
}
}
}
During using long polling the client ends up receiving four messages at once, failing with invalid json. The example below was one string, I added the linebreaks manually.
Invalid JSON from server:
for(;;);[{"syncId":17,"clientId":0,"meta":{"async":true},"changes":[{"node":8,"type":"clear","feat":2},{"node":8,"type":"splice","feat":2,"index":0,"addNodes":[125]
},{"node":8,"type":"splice","feat":2,"index":1,"addNodes":[127]
},{"node":120,"type":"detach"},{"node":121,"type":"detach"},{"node":122,"type":"detach"},{"node":123,"type":"detach"},{"node":124,"type":"attach"},{"node":124,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":125,"type":"attach"},{"node":125,"type":"clear","feat":2},{"node":125,"type":"splice","feat":2,"index":0,"addNodes":[124]
},{"node":125,"type":"put","key":"tag","feat":0,"value":"label"},{"node":126,"type":"attach"},{"node":126,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":127,"type":"attach"},{"node":127,"type":"clear","feat":2},{"node":127,"type":"splice","feat":2,"index":0,"addNodes":[126]
},{"node":127,"type":"put","key":"tag","feat":0,"value":"label"}],"timings":[246774,1]
}]
for(;;);[{"syncId":18,"clientId":0,"meta":{"async":true},"changes":[{"node":8,"type":"clear","feat":2},{"node":8,"type":"splice","feat":2,"index":0,"addNodes":[129]
},{"node":8,"type":"splice","feat":2,"index":1,"addNodes":[131]
},{"node":124,"type":"detach"},{"node":125,"type":"detach"},{"node":126,"type":"detach"},{"node":127,"type":"detach"},{"node":128,"type":"attach"},{"node":128,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":129,"type":"attach"},{"node":129,"type":"clear","feat":2},{"node":129,"type":"splice","feat":2,"index":0,"addNodes":[128]
},{"node":129,"type":"put","key":"tag","feat":0,"value":"label"},{"node":130,"type":"attach"},{"node":130,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":131,"type":"attach"},{"node":131,"type":"clear","feat":2},{"node":131,"type":"splice","feat":2,"index":0,"addNodes":[130]
},{"node":131,"type":"put","key":"tag","feat":0,"value":"label"}],"timings":[246774,1]
}]
for(;;);[{"syncId":19,"clientId":0,"meta":{"async":true},"changes":[{"node":8,"type":"clear","feat":2},{"node":8,"type":"splice","feat":2,"index":0,"addNodes":[133]
},{"node":8,"type":"splice","feat":2,"index":1,"addNodes":[135]
},{"node":128,"type":"detach"},{"node":129,"type":"detach"},{"node":130,"type":"detach"},{"node":131,"type":"detach"},{"node":132,"type":"attach"},{"node":132,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":133,"type":"attach"},{"node":133,"type":"clear","feat":2},{"node":133,"type":"splice","feat":2,"index":0,"addNodes":[132]
},{"node":133,"type":"put","key":"tag","feat":0,"value":"label"},{"node":134,"type":"attach"},{"node":134,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":135,"type":"attach"},{"node":135,"type":"clear","feat":2},{"node":135,"type":"splice","feat":2,"index":0,"addNodes":[134]
},{"node":135,"type":"put","key":"tag","feat":0,"value":"label"}],"timings":[246774,1]
}]
for(;;);[{"syncId":20,"clientId":0,"meta":{"async":true},"changes":[{"node":8,"type":"clear","feat":2},{"node":8,"type":"splice","feat":2,"index":0,"addNodes":[137]
},{"node":8,"type":"splice","feat":2,"index":1,"addNodes":[139]
},{"node":132,"type":"detach"},{"node":133,"type":"detach"},{"node":134,"type":"detach"},{"node":135,"type":"detach"},{"node":136,"type":"attach"},{"node":136,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":137,"type":"attach"},{"node":137,"type":"clear","feat":2},{"node":137,"type":"splice","feat":2,"index":0,"addNodes":[136]
},{"node":137,"type":"put","key":"tag","feat":0,"value":"label"},{"node":138,"type":"attach"},{"node":138,"type":"put","key":"text","feat":7,"value":"anonymous"},{"node":139,"type":"attach"},{"node":139,"type":"clear","feat":2},{"node":139,"type":"splice","feat":2,"index":0,"addNodes":[138]
},{"node":139,"type":"put","key":"tag","feat":0,"value":"label"}],"timings":[246774,1]
}]
In the message it can be seen that the client received multiple updates at once. This can be seen by having the for(; more than once in the message.
Is this expected behaviour? I guess not. But what leads to the issue? And - shouldn’t the client be able to parse it? I believe it fails because the next for(; is not separated from the previous message.
Please clarify whats going on here please.