I am trying to learn GAE's channel API (using Java), but I cannot figure out where to start from.
I went through Channel API Overview (Java) but the code posted there wasn't complete for brevity purposes.
And since I m newbie, it would be very helpful if complete example code is available.
Thanks, Shrey
The code in the Channel API Overview that you've linked to is pretty complete, it's just a bit all over the place. I will admit, once you understand it, I feel like it's much simpler than how they've made it seem, but I'm glad they erred on the side of providing too much information.
It's a bit hard to give a complete solution for this without extraneous information bleeding in, since some of how you'll use the Channel API is a bit dependent on your existing app's infrastructure. For that reason, I've tried to just elaborate a bit on what the AppEngine docs provide, so that hopefully you can understand better. And comments will allow you to ask specific questions, should you have any.
Firstly, a bit of vocabulary:
On the server, you will need to execute the following:
ChannelService channelService = ChannelServiceFactory.getChannelService();
// The channelKey can be generated in any way that you want, as long as it remains
// unique to the user.
String channelKey = "xyz";
String token = channelService.createChannel(channelKey);
Once you have the token, you just need some way to get it to the client-side code. The AppEngine doc that you've linked to does this by serving the HTML from the Java servlet and calling index.replaceAll("\\{\\{ token \\}\\}", token)
.
How this works is that they've done is put the literal string {{ token }}
in their JavaScript code (as you'll see below), so wherever {{ token }}
appears in the JavaScript code, it will be replaced by the actual token generated by the channelService.createChannel(...)
call above. Note that you don't need to inject the token into the client-side code that you're serving in this manner, but it's a good place to start, since that's how they've done it (and documented it).
Now that you've sort of injected the token into the JavaScript, you need to get the code with the channel token to the client. (Note that, as stated above, you can also get just the token to the client, and create the channel that way). The code as they have it is:
<body>
<script>
channel = new goog.appengine.Channel('{{ token }}');
socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onerror = onError;
socket.onclose = onClose;
</script>
</body>
They cut out the details on how to read this from a file on the server, but again, you can do that in any way you like. You could also just literally print the String using resp.getWriter().print(index)
in your JavaServlet, where index
is a String storing the HTML/JavaScript content listed above. Like I said initially, a lot is left up to you what suits your app's existing infrastructure best.
They intend for you to define your own JavaScript functions onOpened
, onMessage
, onError
, and onClose
to be called when channels are opened, receive a message, encounter an error, or are closed, respectively. You may wish to just create naive implementations to better understand what's going on:
function onOpened() {
alert("Channel opened!");
}
function onMessage(msg) {
alert(msg.data);
}
function onError(err) {
alert(err);
}
function onClose() {
alert("Channel closed!");
}
I still recommend separating them out into separate functions, so that you can more easily expand upon them to play around and figure things out. For more details on the JavaScript API, see the Channel API JavaScript Reference.
You'll need to establish a mechanism to get the data that you want to send from the client to the server. Once again, how you wish to do that does not matter. The AppEngine documentation suggests setting up an XMLHttpRequest
to serve that purpose.
sendMessage = function(path, opt_param) {
path += '?g=' + state.game_key;
if (opt_param) {
path += '&' + opt_param;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send();
};
Here, opt_param
is just a string of optional parameters in the format x=1&y=2&z=3
. This is all infrastructure they've built for their sample Tic-Tac-Toe app, and is not crucial to the functionality of the Channel API; like I said, you can make this call however you want.
path
is the path to your servlet (that you will need to set up in your web.xml file) that should handle message sending and receiving (see the following section).
After you have sent the message from the client to the server, you will need a servlet that can send an update to all clients with the same channel key.
ChannelService channelService = ChannelServiceFactory.getChannelService();
// This channelKey needs to be the same as the one in the first section above.
String channelKey = "xyz"
// This is what actually sends the message.
channelService.sendMessage(new ChannelMessage(channelKey, "Hello World!"));
The channelService.sendMessage(...)
call above is what actually sends the message, so that it may be received by the onMessage
function that you defined in the previous section.
I hope this answer is complete (and for that matter, correct) enough to help you get started. Most of what they've put in the docs (and my code here) can be copied and pasted, with only minor tweaks.