blob: 4c7e854dd1ff30469f0e7ec9c1396e3ef2e84088 [file] [log] [blame]
<!doctype html>
<html class="no-js" lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Using the WebSocket API in a Web Application</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Using the WebSocket API in a Web Application - Apache NetBeans">
<meta name="author" content="Apache NetBeans">
<meta name="description" content="Using the WebSocket API in a Web Application - Apache NetBeans">
<meta name="keywords" content="Apache NetBeans, Tutorials, Using the WebSocket API in a Web Application">
<meta name="generator" content="Apache NetBeans">
<link rel="stylesheet" href="../../../../../../_/css/font-awesome.min.css">
<link rel="alternate" type="application/atom+xml" title="Apache NetBeans Blog" href="https://netbeans.apache.org/blogs/atom" />
<link rel="stylesheet" href="../../../../../../_/css/highlightjs/default.min.css">
<link rel="stylesheet" href="../../../../../../_/css/netbeans.css">
<link rel="apple-touch-icon" sizes="180x180" href="../../../../../../_/images/fav/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../../../../../../_/images/fav/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../../../../../../_/images/fav/favicon-16x16.png">
<link rel="manifest" href="../../../../../../_/images/fav/site.webmanifest">
<link rel="mask-icon" href="../../../../../../_/images/fav/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#ffc40d">
<meta name="theme-color" content="#ffffff">
<link href="../../../../../../_/css/font-open-sans.css" rel="stylesheet">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
</head>
<body>
<div class="title-bar" data-responsive-toggle="responsive-menu" data-hide-for="medium">
<button type="button" data-toggle="responsive-menu"><i style='font-size: 32px; color: #fff; padding: 8px' class='fa fa-bars'></i></button>
<div class="title-bar-title">Apache NetBeans</div>
</div>
<div class="top-bar" id="responsive-menu">
<div class='top-bar-left'>
<a class='title' href="../../../../../../index.html"><img src='../../../../../../_/images/apache-netbeans.svg' style='padding: 8px; height: 48px;'> Apache NetBeans</a>
</div>
<div class="top-bar-right">
<ul class="vertical medium-horizontal menu" data-responsive-menu="drilldown medium-dropdown">
<li> <input id="search-input" type="text" placeholder="Search the docs"> </li>
<li> <a href="../../../../../../front/main/community">Community</a> </li>
<li> <a href="../../../../../../front/main/participate">Participate</a> </li>
<li> <a href="../../../../../../front/main/blogs">Blog</a></li>
<li> <a href="../../../../../../front/main/help">Get Help</a> </li>
<li> <a href="https://plugins.netbeans.apache.org/">Plugins</a> </li>
<li> <a href="../../../../../../front/main/download">Download</a> </li>
</ul>
</div>
</div>
<!-- src/templates/news -->
<section class="hero news alternate">
<div class='grid-container'>
<div class='cell'>
<div class="annotation">Latest release</div>
<h1>Apache NetBeans 28</h1>
<p><a class="button success" href="../../../../../../front/main/download/nb28">Download</a></p>
</div>
</div>
</section>
<div class='grid-container main-content tutorial'>
<article class="doc">
<h1 class="sect0">Using the WebSocket API in a Web Application</h1>
<div class="sectionbody">
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon"><i class="fa icon-note" title="Note"></i></td>
<td class="content">This tutorial needs a review.
You can <a href="https://github.com/apache/netbeans-antora-tutorials/edit/main/modules/ROOT/pages/kb/docs/javaee/maven-websocketapi.adoc" title="Edit this tutorial in github">edit it in GitHub </a>
following these <a href="../../../../../../tutorial/main/kb/docs/contributing">contribution guidelines.</a></td>
</tr></tbody>
</table>
</div>
</div>
<div id="toc" class="toc">
<div id="toctitle"></div>
<ul class="sectlevel1">
<li><a href="#_creating_the_web_application_project">Creating the Web Application Project</a></li>
<li><a href="#_creating_the_websocket_endpoint">Creating the WebSocket Endpoint</a>
<ul class="sectlevel2">
<li><a href="#_creating_the_endpoint">Creating the Endpoint</a></li>
<li><a href="#_initiate_the_websocket_session">Initiate the WebSocket Session</a></li>
<li><a href="#_testing_the_endpoint">Testing the Endpoint</a></li>
</ul>
</li>
<li><a href="#_creating_the_whiteboard">Creating the Whiteboard</a>
<ul class="sectlevel2">
<li><a href="#_add_the_canvas_to_the_web_page">Add the Canvas to the Web Page</a></li>
<li><a href="#_creating_the_pojo">Creating the POJO</a></li>
<li><a href="#_create_a_coordinates_class">Create a Coordinates Class</a></li>
<li><a href="#_generate_the_json_string">Generate the JSON String</a></li>
<li><a href="#_implement_the_encoder_and_decoder_interfaces">Implement the Encoder and Decoder Interfaces</a></li>
<li><a href="#_running_the_application">Running the Application</a></li>
</ul>
</li>
<li><a href="#_sending_binary_data_to_the_endpoint">Sending Binary Data to the Endpoint</a></li>
<li><a href="#_see_also">See Also</a></li>
</ul>
</div>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This tutorial demonstrates how to create a simple web application that enables collaboration between client browsers that are connected to a single server application. When a user draws a graphic element on a canvas in the client browser the element appears on the canvas of all connected clients. How does it work? When the browser loads the web page a client-side script sends a WebSocket handshake request to the application server. The application can accept JSON and binary messages from the clients connected in the session and broadcast the messages to all the connected clients.</p>
</div>
<div class="paragraph">
<p>In this tutorial you will create a web application that uses the Java API for WebSocket (<a href="http://www.jcp.org/en/jsr/detail?id=356">JSR 356</a>) to enable bi-directional communication between browser clients and the application server. The Java API for WebSocket provides support for creating WebSocket Java components, initiating and intercepting WebSocket events and creating and consuming WebSocket text and binary messages. The tutorial will also demonstrate how you can use the Java API for JSON Processing (<a href="http://jcp.org/en/jsr/detail?id=353">JSR 353</a>) to produce and consume JSON. The Java API for WebSocket and the Java API for JSON Processing are part of the Java EE 7 platform (<a href="http://jcp.org/en/jsr/detail?id=342">JSR 342</a>).</p>
</div>
<div class="paragraph">
<p>The application contains a WebSocket endpoint and decoder and encoder interfaces, a web page and some JavaScript files that are run in the client browser when the page is loaded or when invoked from a form in the web page. You will deploy the application to GlassFish Server Open Source Edition 4, the reference implementation of Java EE 7 technology.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
This tutorial is based on the <a href="https://blogs.oracle.com/arungupta/entry/collaborative_whiteboard_using_websocket_in">+ Collaborative Whiteboard using WebSocket in GlassFish 4 - Text/JSON and Binary/ArrayBuffer Data Transfer (TOTD #189) ] blog post and other blog entries which can be found on link:http://blog.arungupta.me/[+Arun Gupta's blog</a>. Be sure to visit the blog and see many other excellent entries on working with the WebSocket API and GlassFish 4.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can also watch the <a href="../maven-websocketapi-screencast/" class="xref page">Video of Using the WebSocket API in a Web Application</a>.</p>
</div>
<div class="paragraph">
<p><strong>Tutorial Exercises</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#Exercise_1">Creating the Web Application Project</a></p>
</li>
<li>
<p><a href="#createendpoint">Creating the WebSocket Endpoint</a></p>
</li>
<li>
<p><a href="#createendpoint1">Create the Endpoint</a></p>
</li>
<li>
<p><a href="#createendpoint2">Initiate the WebSocket Session</a></p>
</li>
<li>
<p><a href="#createendpoint3">Test the Endpoint</a></p>
</li>
<li>
<p><a href="#createwhiteboard">Creating the Whiteboard</a></p>
</li>
<li>
<p><a href="#createwhiteboard1">Add the Canvas</a></p>
</li>
<li>
<p><a href="#createwhiteboard2">Create the POJO</a></p>
</li>
<li>
<p><a href="#createwhiteboard3">Create a Coordinates Class</a></p>
</li>
<li>
<p><a href="#createwhiteboard6">Generate the JSON String</a></p>
</li>
<li>
<p><a href="#createwhiteboard4">Implement the Encoder and Decoder Interfaces</a></p>
</li>
<li>
<p><a href="#createwhiteboard5">Run the Application</a></p>
</li>
<li>
<p><a href="#sendbinary">Sending Binary Data to the Endpoint</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>To follow this tutorial, you need the following software and resources.</strong></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Software or Resource</th>
<th class="tableblock halign-left valign-top">Version Required</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../../../../../../front/main/download/" class="xref page">NetBeans IDE</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">7.3.1, 7.4, 8.0, Java EE version</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Java Development Kit (JDK)</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">version 7 or 8</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://glassfish.java.net/">GlassFish Server Open Source Edition</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
</tr>
</tbody>
</table>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
GlassFish 4 is bundled with the Java EE download bundle of NetBeans IDE.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><strong>Prerequisites</strong></p>
</div>
<div class="paragraph">
<p>This document assumes you have some basic knowledge of, or programming experience with, the following technologies:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Java Programming</p>
</li>
<li>
<p>JavaScript/HTML Programming</p>
</li>
<li>
<p>NetBeans IDE</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Before starting this tutorial you may want to familiarize yourself with the following documentation.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="../../../../../../wiki/main/wiki/MavenBestPractices/" class="xref page">Best Practices for Apache Maven in NetBeans IDE</a></p>
</li>
<li>
<p><a href="http://books.sonatype.com/mvnref-book/reference/introduction.html">Chapter 1. Introducing Apache Maven</a> (from <a href="http://books.sonatype.com/mvnref-book/reference/index.html">+Maven: The Complete Reference +</a>)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You can download <a href="http://web.archive.org/web/20210118011547/https://netbeans.org/project_downloads/samples/Samples/JavaEE/WhiteboardApp.zip">a zip archive of the finished project</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_the_web_application_project"><a class="anchor" href="#_creating_the_web_application_project"></a>Creating the Web Application Project</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The goal of this exercise is to create a web application project using the New Project wizard in the IDE. When you create the project you will select Java EE 7 as the Java EE version and GlassFish 4 as the application server. GlassFish 4 is the reference implementation of the Java EE 7 platform. You must have an application server that supports Java EE 7 registered with the IDE to create the application in this tutorial.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Choose File &gt; New Project (Ctrl-Shift-N on Windows; ⌘-Shift-N on Mac) from the main menu.</p>
</li>
<li>
<p>Select Web Application from the Maven category. Click Next.</p>
</li>
<li>
<p>Type <strong>WhiteboardApp</strong> for the the Project Name and set the Project Location.</p>
</li>
<li>
<p>Type <strong>org.sample</strong> for the Group Id. Click Next.</p>
</li>
<li>
<p>Select <strong>GlassFish Server 4.0</strong> for the Server.</p>
</li>
<li>
<p>Set the Java EE Version to <strong>Java EE 7 Web</strong>. Click Finish.</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-newproject.png" alt="websocket newproject">
</div>
<div class="title">Figure 1. Server and Java EE versions in the New Project wizard</div>
</div>
<div class="paragraph">
<p>When you click Finish, the IDE creates the project and opens the project in the Projects window.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_the_websocket_endpoint"><a class="anchor" href="#_creating_the_websocket_endpoint"></a>Creating the WebSocket Endpoint</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this section you will create a WebSocket endpoint class and a JavaScript file. The WebSocket endpoint class contains some basic methods that are run when the session is opened. You will then create a JavaScript file that will initiate the handshake with the server when the page is loaded. You will then run the application to test that the connection is successful.</p>
</div>
<div class="paragraph">
<p>For more about using WebSocket APIs and annotations, see the summary of the <a href="https://javaee-spec.java.net/nonav/javadocs/javax/websocket/package-summary.html">+ javax.websocket+</a> package.</p>
</div>
<div class="sect2">
<h3 id="_creating_the_endpoint"><a class="anchor" href="#_creating_the_endpoint"></a>Creating the Endpoint</h3>
<div class="paragraph">
<p>In this exercise you will use a wizard in the IDE to help you create the WebSocket endpoint class.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the Source Packages node in the Projects window and choose New &gt; Other.</p>
</li>
<li>
<p>Select WebSocket Endpoint in the Web category. Click Next.</p>
</li>
<li>
<p>Type <strong>MyWhiteboard</strong> as the Class Name.</p>
</li>
<li>
<p>Select <code>org.sample.whiteboardapp</code> in the Package dropdown list.</p>
</li>
<li>
<p>Type <strong>/whiteboardendpoint</strong> as the WebSocket URI. Click Finish.</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-newendpoint.png" alt="websocket newendpoint">
</div>
<div class="title">Figure 2. WebSocket Endpoint in the New File wizard</div>
</div>
<div class="paragraph">
<p>When you click Finish the IDE generates the WebSocket Endpoint class and opens the file in the source editor. In the editor you can see that the IDE generated some annotations that are part of the WebSocket API. The class is annotated with <code><a href="https://javaee-spec.java.net/nonav/javadocs/javax/websocket/server/ServerEndpoint.html">@ServerEndpoint</a></code> to identify the class as an endpoint and the WebSocket URI is specified as a parameter of the annotation. The IDE also generated a default <code>onMessage</code> method that is annotated with <code><a href="https://javaee-spec.java.net/nonav/javadocs/javax/websocket/OnMessage.html">@OnMessage</a></code> . A method annotated with <code>@OnMessage</code> is invoked each time that the client receives a WebSocket message.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@ServerEndpoint("/whiteboardendpoint")
public class MyWhiteboard {
@OnMessage
public String onMessage(String message) {
return null;
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following field (in <strong>bold</strong>) to the class.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@ServerEndpoint("/whiteboardendpoint")
public class MyWhiteboard {
*private static Set&lt;Session&gt; peers = Collections.synchronizedSet(new HashSet&lt;Session&gt;());*
@OnMessage
public String onMessage(String message) {
return null;
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following <code>onOpen</code> and <code>onClose</code> methods.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> @OnOpen
public void onOpen (Session peer) {
peers.add(peer);
}
@OnClose
public void onClose (Session peer) {
peers.remove(peer);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can see that the <code>onOpen</code> and <code>onClose</code> methods are annotated with <code><a href="https://javaee-spec.java.net/nonav/javadocs/javax/websocket/OnOpen.html">@OnOpen</a></code> and <code><a href="https://javaee-spec.java.net/nonav/javadocs/javax/websocket/OnClose.html">@OnClose</a></code> WebSocket API annotations. A method annotated with <code>@OnOpen</code> is called when the web socket session is opened. In this example the annotated <code>onOpen</code> method adds the browser client to the group of peers in the current session and the <code>onClose</code> method removes the browser from the group.</p>
</div>
<div class="paragraph">
<p>Use the hints and code completion in the source editor to help you generate the methods. Click the hint glyph in the left margin next to the class declaration (or place the insert cursor in the class declaration and type Alt-Enter) and select the method in the popup menu. The code completion can help you code the method.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-endpoint-hint.png" alt="websocket endpoint hint">
</div>
<div class="title">Figure 3. Code Hint in the Source Editor</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click in the editor and choose Fix Imports (Alt-Shift-I; ⌘-Shift-I on Mac). Save your changes.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>You will see that import statements for classes in <code>javax.websocket</code> are added to the file.</p>
</div>
<div class="paragraph">
<p>The endpoint is now created. You now need to create a JavaScript file to initiate the WebSocket session.</p>
</div>
</div>
<div class="sect2">
<h3 id="_initiate_the_websocket_session"><a class="anchor" href="#_initiate_the_websocket_session"></a>Initiate the WebSocket Session</h3>
<div class="paragraph">
<p>In this exercise you will create a JavaScript file that will initiate a WebSocket session. The browser client joins a session via an HTTP 'handshake' with the server over TCP. In the JavaScript file you will specify the name of the <code>wsURI</code> of the endpoint and declare the WebSocket. The <code>wsURI</code> URI scheme is part of the WebSocket protocol and specifies the path to the endpoint for the application.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project node in the Projects window and choose New &gt; Other.</p>
</li>
<li>
<p>Select JavaScript File in the Web category of the New File wizard. Click Next.</p>
</li>
<li>
<p>Type <strong>websocket</strong> for the JavaScript File Name. Click Finish.</p>
</li>
<li>
<p>Add the following to the JavaScript file.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">var wsUri = "ws://" + document.location.host + document.location.pathname + "whiteboardendpoint";
var websocket = new WebSocket(wsUri);
websocket.onerror = function(evt) { onError(evt) };
function onError(evt) {
writeToScreen('&lt;span style="color: red;"&gt;ERROR:&lt;/span&gt; ' + evt.data);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This script will initiate the session handshake with the server when <code>websocket.js</code> is loaded by the browser.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>index.html</code> and add the following code (in <strong>bold</strong>) to the bottom of the file to load <code>websocket.js</code> when the page is finished loading.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;body&gt;
*&lt;h1&gt;Collaborative Whiteboard App&lt;/h1&gt;
&lt;script type="text/javascript" src="websocket.js"&gt;&lt;/script&gt;*
&lt;/body&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can now test that the WebSocket endpoint is working and that the session is started and the client is added to the session.</p>
</div>
</div>
<div class="sect2">
<h3 id="_testing_the_endpoint"><a class="anchor" href="#_testing_the_endpoint"></a>Testing the Endpoint</h3>
<div class="paragraph">
<p>In this exercise you will add some some simple methods to the JavaScript file to print the <code>wsURI</code> to the browser window when the browser is connected to the endpoint.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following <code>&lt;div&gt;</code> tag (in <strong>bold</strong>) to <code>index.html</code></p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;h1&gt;Collaborative Whiteboard App&lt;/h1&gt;
*&lt;div id="output"&gt;&lt;/div&gt;*
&lt;script type="text/javascript" src="websocket.js"&gt;&lt;/script&gt;</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following declaration and methods to <code>websocket.js</code> . Save your changes.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">// For testing purposes
var output = document.getElementById("output");
websocket.onopen = function(evt) { onOpen(evt) };
function writeToScreen(message) {
output.innerHTML += message + "&lt;br&gt;";
}
function onOpen() {
writeToScreen("Connected to " + wsUri);
}
// End test functions</code></pre>
</div>
</div>
<div class="paragraph">
<p>When the page loads the JavaScript functions will print the message that the browser is connected to the endpoint. You can delete the functions after you confirm that the endpoint is performing correctly.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project in the Projects window and choose Run.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>When you run the application the IDE will start the GlassFish server and build and deploy the application. The index page will open in your browser and you will see the following message in the browser window.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-browser1.png" alt="websocket browser1">
</div>
<div class="title">Figure 4. Connected to endpoint message in browser window</div>
</div>
<div class="paragraph">
<p>In the browser window you can see the following endpoint where messages are accepted: <code><a href="http://localhost:8080/WhiteboardApp/whiteboardendpoint" class="bare">http://localhost:8080/WhiteboardApp/whiteboardendpoint</a></code></p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_creating_the_whiteboard"><a class="anchor" href="#_creating_the_whiteboard"></a>Creating the Whiteboard</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this section you will create the classes and JavaScript files to send and receive JSON text messages. You will also add an <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html">HTML5 Canvas</a> element for painting and displaying some content and an HTML <code>&lt;form&gt;</code> with radio buttons that enable you to specify the shape and color of the paintbrush.</p>
</div>
<div class="sect2">
<h3 id="_add_the_canvas_to_the_web_page"><a class="anchor" href="#_add_the_canvas_to_the_web_page"></a>Add the Canvas to the Web Page</h3>
<div class="paragraph">
<p>In this exercise you add a <code>canvas</code> element and a <code>form</code> element to the default index page. The checkboxes in the form determine the properties of the paintbrush for the canvas.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>index.html</code> in the source editor.</p>
</li>
<li>
<p>Delete the <code>&lt;div&gt;</code> tag that you added to test the endpoint and add the following <code>&lt;table&gt;</code> and <code>&lt;form&gt;</code> elements (in <strong>bold</strong>) after the opening body tag.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;h1&gt;Collaborative Whiteboard App&lt;/h1&gt;
*&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;form name="inputForm"&gt;
&lt;/form&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;*
&lt;script type="text/javascript" src="websocket.js"&gt;&lt;/script&gt;
&lt;/body&gt;</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following code (in <strong>bold</strong>) for the canvas element.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html"> &lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
*&lt;canvas id="myCanvas" width="150" height="150" style="border:1px solid #000000;"&gt;&lt;/canvas&gt;*
&lt;/td&gt;</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following <code>&lt;table&gt;</code> to add radio buttons to select the color and shape. Save your changes.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html"> &lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;canvas id="myCanvas" width="150" height="150" style="border:1px solid #000000;"&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;form name="inputForm"&gt;
*&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Color&lt;/th&gt;
&lt;td&gt;&lt;input type="radio" name="color" value="#FF0000" checked="true"&gt;Red&lt;/td&gt;
&lt;td&gt;&lt;input type="radio" name="color" value="#0000FF"&gt;Blue&lt;/td&gt;
&lt;td&gt;&lt;input type="radio" name="color" value="#FF9900"&gt;Orange&lt;/td&gt;
&lt;td&gt;&lt;input type="radio" name="color" value="#33CC33"&gt;Green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Shape&lt;/th&gt;
&lt;td&gt;&lt;input type="radio" name="shape" value="square" checked="true"&gt;Square&lt;/td&gt;
&lt;td&gt;&lt;input type="radio" name="shape" value="circle"&gt;Circle&lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;*
&lt;/form&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The shape, color, and coordinates of any figure drawn on the canvas will be converted to a string in a JSON structure and sent as a message to the WebSocket endpoint.</p>
</div>
</div>
<div class="sect2">
<h3 id="_creating_the_pojo"><a class="anchor" href="#_creating_the_pojo"></a>Creating the POJO</h3>
<div class="paragraph">
<p>In this exercise you will create a simple POJO.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project node and choose New &gt; Java Class.</p>
</li>
<li>
<p>Type <strong>Figure</strong> as the Class Name and choose <code>org.sample.whiteboardapp</code> in the Package dropdown list. Click Finish.</p>
</li>
<li>
<p>In the source editor, add the following (in <strong>bold</strong>):</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class Figure {
*private JsonObject json;*
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>When you add the code you will be prompted to add an import statement for <code>javax.json.JsonObject</code> . If you are not prompted, type Alt-Enter.</p>
</div>
<div class="paragraph">
<p>For more about <code>javax.json.JsonObject</code> , see the Java API for JSON Processing (<a href="http://jcp.org/en/jsr/detail?id=353">JSR 353</a>), which is part of the Java EE 7 Specification.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Create a getter and setter for <code>json</code> .</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>You can select getter and setter in the Insert Code popup menu (Alt-Ins on Windows; Ctrl-I on Mac) to open the Generate Getters and Setter dialog box. Alternatively, you can choose Source &gt; Insert Code from the main menu.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-generategetter.png" alt="websocket generategetter">
</div>
<div class="title">Figure 5. Generate Getter and Setter dialog box</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add a constructor for <code>json</code> .</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> public Figure(JsonObject json) {
this.json = json;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can choose Constructor in the Insert Code popup menu (Ctrl-I).</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-generateconstructor.png" alt="websocket generateconstructor">
</div>
<div class="title">Figure 6. Generate Constructor popup menu</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following <code>toString</code> method:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> @Override
public String toString() {
StringWriter writer = new StringWriter();
Json.createWriter(writer).write(json);
return writer.toString();
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click in the editor and choose Fix Imports (Alt-Shift-I; ⌘-Shift-I on Mac). Save your changes.</p>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="_create_a_coordinates_class"><a class="anchor" href="#_create_a_coordinates_class"></a>Create a Coordinates Class</h3>
<div class="paragraph">
<p>You now create a class for the coordinates of the figures that are painted on the canvas.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project node and choose New &gt; Java Class.</p>
</li>
<li>
<p>In the New Java Class wizard, type <strong>Coordinates</strong> as the Class Name and select <code>org.sample.whiteboardapp</code> in the Package dropdown list. Click Finish.</p>
</li>
<li>
<p>In the source editor, add the following code. Save your changes.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> private float x;
private float y;
public Coordinates() {
}
public Coordinates(float x, float y) {
this.x = x;
this.y = y;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The class only contains a fields for the <code>x</code> and <code>y</code> coordinates and some getters and setters.</p>
</div>
</div>
<div class="sect2">
<h3 id="_generate_the_json_string"><a class="anchor" href="#_generate_the_json_string"></a>Generate the JSON String</h3>
<div class="paragraph">
<p>In this exercise you will create a JavaScript file that puts the details of the figure that is drawn on the <code>canvas</code> element into a JSON structure that is sent to the websocket endpoint.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project node and choose New &gt; JavaScript File to open the New JavaScript File wizard.</p>
</li>
<li>
<p>Type <strong>whiteboard</strong> for the File Name. Click Finish.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>When you click Finish the IDE creates the empty JavaScript file and opens the file in the editor. You can see the new file under the Web Pages node in the Projects window.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following code to initialize the canvas and to add an event listener.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
canvas.addEventListener("click", defineImage, false);</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can see that the <code>defineImage</code> method is invoked when the user clicks in the <code>canvas</code> element.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following <code>getCurrentPos</code> , <code>defineImage</code> and <code>drawImageText</code> methods to construct the JSON structure and send it to the endpoint ( <code>sendText(json)</code> ).</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">function getCurrentPos(evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function defineImage(evt) {
var currentPos = getCurrentPos(evt);
for (i = 0; i &lt; document.inputForm.color.length; i++) {
if (document.inputForm.color[i].checked) {
var color = document.inputForm.color[i];
break;
}
}
for (i = 0; i &lt; document.inputForm.shape.length; i++) {
if (document.inputForm.shape[i].checked) {
var shape = document.inputForm.shape[i];
break;
}
}
var json = JSON.stringify({
"shape": shape.value,
"color": color.value,
"coords": {
"x": currentPos.x,
"y": currentPos.y
}
});
drawImageText(json);
sendText(json);
}
function drawImageText(image) {
console.log("drawImageText");
var json = JSON.parse(image);
context.fillStyle = json.color;
switch (json.shape) {
case "circle":
context.beginPath();
context.arc(json.coords.x, json.coords.y, 5, 0, 2 * Math.PI, false);
context.fill();
break;
case "square":
default:
context.fillRect(json.coords.x, json.coords.y, 10, 10);
break;
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The JSON structure that is sent will be similar to the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">{
"shape": "square",
"color": "#FF0000",
"coords": {
"x": 31.59999942779541,
"y": 49.91999053955078
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You now need to add a <code>sendText(json)</code> method to send the JSON string using <code>websocket.send()</code> .</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>websocket.js</code> in the editor and add the following methods for sending JSON to the endpoint and for drawing the image when a message is received from the endpoint.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">websocket.onmessage = function(evt) { onMessage(evt) };
function sendText(json) {
console.log("sending text: " + json);
websocket.send(json);
}
function onMessage(evt) {
console.log("received: " + evt.data);
drawImageText(evt.data);
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
You can delete the code that you added to <code>websocket.js</code> for testing the endpoint.
</td>
</tr>
</table>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following line (in <strong>bold</strong>) to the bottom of <code>index.html</code> to load <code>whiteboard.js</code> .</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html"> &lt;/table&gt;
&lt;script type="text/javascript" src="websocket.js"&gt;&lt;/script&gt;
*&lt;script type="text/javascript" src="whiteboard.js"&gt;&lt;/script&gt;*
&lt;body&gt;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_implement_the_encoder_and_decoder_interfaces"><a class="anchor" href="#_implement_the_encoder_and_decoder_interfaces"></a>Implement the Encoder and Decoder Interfaces</h3>
<div class="paragraph">
<p>In this exercise you create classes to implement decoder and encoder interfaces to decode web socket messages (JSON) to the POJO class <code>Figure</code> and to encode <code>Figure</code> as a JSON string for sending to the endpoint.</p>
</div>
<div class="paragraph">
<p>For more details, see the section about message types and encoders and decoders in the technical article <a href="http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html">JSR 356, Java API for WebSocket</a>.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project node and choose New &gt; Java Class.</p>
</li>
<li>
<p>Type <strong>FigureEncoder</strong> as the Class Name and choose <code>org.sample.whiteboardapp</code> in the Package dropdown list. Click Finish.</p>
</li>
<li>
<p>In the source editor, implement the WebSocket Encoder interface by adding the following code (in <strong>bold</strong>):</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class FigureEncoder *implements Encoder.Text&lt;Figure&gt;* {
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add an import statement for <code>javax.websocket.Encoder</code> and implement the abstract methods.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Place your cursor in the class declaration and type Alt-Enter and choose <strong>Implement all abstract methods</strong> from the popup menu.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Modify the generated abstract methods by making the following changes (in <strong>bold</strong>). Save your changes.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> @Override
public String encode(Figure *figure*) throws EncodeException {
*return figure.getJson().toString();*
}
@Override
public void init(EndpointConfig ec) {
*System.out.println("init");*
}
@Override
public void destroy() {
*System.out.println("destroy");*
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click the project node and choose New &gt; Java Class.</p>
</li>
<li>
<p>Type <strong>FigureDecoder</strong> as the Class Name and choose <code>org.sample.whiteboardapp</code> in the Package dropdown list. Click Finish.</p>
</li>
<li>
<p>In the source editor, implement the WebSocket Decoder interface by adding the following code (in <strong>bold</strong>):</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class FigureDecoder *implements Decoder.Text&lt;Figure&gt;* {
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add an import statement for <code>javax.websocket.Decoder</code> and implement abstract methods.</p>
</li>
<li>
<p>Make the following changes (in <strong>bold</strong>) to the generated abstract methods.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> @Override
public Figure decode(String *string*) throws DecodeException {
*JsonObject jsonObject = Json.createReader(new StringReader(string)).readObject();
return new Figure(jsonObject);*
}
@Override
public boolean willDecode(String *string*) {
*try {
Json.createReader(new StringReader(string)).readObject();
return true;
} catch (JsonException ex) {
ex.printStackTrace();
return false;
}*
}
@Override
public void init(EndpointConfig ec) {
*System.out.println("init");*
}
@Override
public void destroy() {
*System.out.println("destroy");*
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Fix the imports and save your changes.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>You now need to modify <code>MyWhiteboard.java</code> to specify the encoder and decoder.</p>
</div>
</div>
<div class="sect2">
<h3 id="_running_the_application"><a class="anchor" href="#_running_the_application"></a>Running the Application</h3>
<div class="paragraph">
<p>You are now almost ready to run the application. In this exercise you modify the WebSocket endpoint class to specify the encoder and decoder for the JSON string and to add a method to send the JSON string to connected clients when a message is received.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>MyWhiteboard.java</code> in the editor.</p>
</li>
<li>
<p>Modify the <code>@ServerEndpoint</code> annotation to specify the encoder and decoder for the endopoint. Note that you need to explicitly specify the <code>value</code> parameter for the name of the endpoint.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@ServerEndpoint(*value=*"/whiteboardendpoint"*, encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class}*)</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Delete the <code>onMessage</code> method that was generated by default.</p>
</li>
<li>
<p>Add the following <code>broadcastFigure</code> method and annotate the method with <code>@OnMessage</code> .</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java"> @OnMessage
public void broadcastFigure(Figure figure, Session session) throws IOException, EncodeException {
System.out.println("broadcastFigure: " + figure);
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getBasicRemote().sendObject(figure);
}
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Right-click in the editor and choose Fix Imports (Alt-Shift-I; ⌘-Shift-I on Mac). Save your changes.</p>
</li>
<li>
<p>Right-click the project in the Projects window and choose Run.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>When you click Run the IDE opens a browser window to <a href="http://localhost:8080/WhiteboardApp/">http://localhost:8080/WhiteboardApp/</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
You might need to undeploy the previous application from the application server or force reload the page in the browser.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>If you view the browser messages you can see that a string is sent via JSON to the endpoint each time you click in the canvas.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-onebrowser.png" alt="websocket onebrowser">
</div>
<div class="title">Figure 7. Canvas with figures in browser and JSON displayed in web console</div>
</div>
<div class="paragraph">
<p>If you open another browser to <code><a href="http://localhost:8080/WhiteboardApp/" class="bare">http://localhost:8080/WhiteboardApp/</a></code> you can see that each time you click in the canvas in one browser the new circle or square is reproduced in the canvas of the other browser.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-twobrowsers.png" alt="websocket twobrowsers">
</div>
<div class="title">Figure 8. Two browsers sending JSON via the endpoint</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_sending_binary_data_to_the_endpoint"><a class="anchor" href="#_sending_binary_data_to_the_endpoint"></a>Sending Binary Data to the Endpoint</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The application can now process and send a string via JSON to the endpoint and the string is then sent to the connected clients. In this section you will modify the JavaScript files to send and receive binary data.</p>
</div>
<div class="paragraph">
<p>To send binary data to the endpoint you need to set the <code>binaryType</code> property of WebSocket to <code>arraybuffer</code> . This ensures that any binary transfers using WebSocket are done using <code>ArrayBuffer</code> . The binary data conversion is performed by the <code>defineImageBinary</code> method in <code>whiteboard.js</code> .</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>websocket.js</code> and add the following code to set the <code>binaryType</code> property of WebSocket to <code>arraybuffer</code> .</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">websocket.binaryType = "arraybuffer";</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Add the following method to send binary data to the endpoint.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">function sendBinary(bytes) {
console.log("sending binary: " + Object.prototype.toString.call(bytes));
websocket.send(bytes);
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Modify the <code>onMessage</code> method to add the following code (in <strong>bold</strong>) to select the method for updating the canvas according to the type of data in the incoming message.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">function onMessage(evt) {
console.log("received: " + evt.data);
*if (typeof evt.data == "string") {*
drawImageText(evt.data);
*} else {
drawImageBinary(evt.data);
}*
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>drawImageBinary</code> method is invoked if a message with binary data is received.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>whiteboard.js</code> and add the following methods. The <code>drawImageBinary</code> method is invoked to update the canvas after parsing the incoming binary data. The <code>defineImageBinary</code> method is used to prepare a snapshot of the canvas as binary data.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript">function drawImageBinary(blob) {
var bytes = new Uint8Array(blob);
// console.log('drawImageBinary (bytes.length): ' + bytes.length);
var imageData = context.createImageData(canvas.width, canvas.height);
for (var i=8; i&lt;imageData.data.length; i++) {
imageData.data[i] = bytes[i];
}
context.putImageData(imageData, 0, 0);
var img = document.createElement('img');
img.height = canvas.height;
img.width = canvas.width;
img.src = canvas.toDataURL();
}
function defineImageBinary() {
var image = context.getImageData(0, 0, canvas.width, canvas.height);
var buffer = new ArrayBuffer(image.data.length);
var bytes = new Uint8Array(buffer);
for (var i=0; i&lt;bytes.length; i++) {
bytes[i] = image.data[i];
}
sendBinary(buffer);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You now need to add a way to invoke <code>defineImageBinary</code> when you want to generate the binary data as the type <code>ArrayBuffer</code> and send it to the endpoint.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>index.html</code> and modify the <code>&lt;table&gt;</code> element to add the following row to the table in the form.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;tr&gt;
&lt;th&gt; &lt;/th&gt;
&lt;td&gt;&lt;input type="submit" value="Send Snapshot" onclick="defineImageBinary(); return false;"&gt;&lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;/tr&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The new row contains a Send Snapshot button to send a binary snapshot of the canvas to the connected peers. The <code>defineImageBinary</code> method in <code>whiteboard.js</code> is invoked when the button is clicked.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>MyWhiteboard.java</code> and add the following method that will send the binary data to peers when the endpoint receives a message with binary data.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@OnMessage
public void broadcastSnapshot(ByteBuffer data, Session session) throws IOException {
System.out.println("broadcastBinary: " + data);
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getBasicRemote().sendBinary(data);
}
}
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
You will need to add an import statement for <code>java.nio.ByteBuffer</code> .
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can modify the application to enable the user to stop sending data to the endpoint. By default all peers are connected as soon as they open the page and data is sent from the browser to all connected peers. You can add a simple conditional so that data is not sent to the endpoint unless the option is selected. This does not affect receiving data. Data is still received from the endpoint.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Modify the <code>defineImage</code> method in <code>whiteboard.js</code> to add the following code (in <strong>bold</strong>).</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript hljs" data-lang="javascript"> drawImageText(json);
* if (document.getElementById("instant").checked) {*
sendText(json);
* }*
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The conditional code that you checks that if the element with the id <code>checked</code></p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open <code>index.html</code> and modify the <code>&lt;table&gt;</code> element to add a checkbox to the form.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;tr&gt;
&lt;th&gt; &lt;/th&gt;
&lt;td&gt;&lt;input type="submit" value="Send Snapshot" onclick="defineImageBinary(); return false;"&gt;&lt;/td&gt;
&lt;td&gt;*&lt;input type="checkbox" id="instant" value="Online" checked="true"&gt;Online*&lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;/tr&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>No data is sent when the Online checkbox is deselected, but the client will still receive data from the endpoint.</p>
</div>
<div class="paragraph">
<p>If you add the Send Snapshot button and the Online checkbox and run the application again you will see the new elements in the index page. If you open another browser and deselect the Online button you can see that the JSON message is not sent to the endpoint when you click in the canvas.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../../../_images/kb/docs/javaee/websocket-onebrowser-binary.png" alt="websocket onebrowser binary">
</div>
<div class="title">Figure 9. Web console in browser displaying message that binary data was sent</div>
</div>
<div class="paragraph">
<p>If you click Send Snapshot the binary data is sent to the endpoint and broadcast to the connected clients.</p>
</div>
<div class="paragraph">
<p><a href="../../../../../../front/main/community/mailing-lists/" class="xref page">Send Feedback on This Tutorial</a></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see_also"><a class="anchor" href="#_see_also"></a>See Also</h2>
<div class="sectionbody">
<div class="paragraph">
<p>For more information about using NetBeans IDE to develop Java EE applications, see the following resources:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Demo: <a href="../maven-websocketapi-screencast/" class="xref page">Using the WebSocket API in a Web Application</a></p>
</li>
<li>
<p><a href="../javaee-intro/" class="xref page">Introduction to Java EE Technology</a></p>
</li>
<li>
<p><a href="../javaee-gettingstarted/" class="xref page">Getting Started with Java EE Applications</a></p>
</li>
<li>
<p><a href="../../java-ee/" class="xref page">Java EE &amp;amp; Java Web Learning Trail</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You can find more information about using Java EE in the <a href="http://download.oracle.com/javaee/6/tutorial/doc/">Java EE Tutorial</a>.</p>
</div>
<div class="paragraph">
<p>To send comments and suggestions, get support, and keep informed on the latest developments on the NetBeans IDE Java EE development features, <a href="../../../../../../front/main/community/mailing-lists/" class="xref page">join the nbj2ee mailing list</a>.</p>
</div>
</div>
</div>
<section class='tools'>
<ul class="menu align-center">
<li><a title="Facebook" href="https://www.facebook.com/NetBeans"><i class="fa fa-md fa-facebook"></i></a></li>
<li><a title="Twitter" href="https://twitter.com/netbeans"><i class="fa fa-md fa-twitter"></i></a></li>
<li><a title="Github" href="https://github.com/apache/netbeans"><i class="fa fa-md fa-github"></i></a></li>
<li><a title="YouTube" href="https://www.youtube.com/user/netbeansvideos"><i class="fa fa-md fa-youtube"></i></a></li>
<li><a title="Atom Feed" href="https://netbeans.apache.org/blogs/atom"><i class="fa fa-mf fa-rss"></i></a></li>
<li><a title="Slack" href="https://tinyurl.com/netbeans-slack-signup/"><i class="fa fa-md fa-slack"></i></a></li>
<li><a title="Issues" href="https://github.com/apache/netbeans/issues"><i class="fa fa-mf fa-bug"></i></a></li>
</ul>
<ul class="menu align-center">
<li><a href="https://github.com/apache/netbeans-antora-tutorials/edit/main/modules/ROOT/pages/kb/docs/javaee/maven-websocketapi.adoc" title="See this page in github"><i class="fa fa-md fa-edit"></i> See this page in GitHub.</a></li>
</ul>
</section>
</article>
</div>
<div class='grid-container incubator-area' style='margin-top: 64px'>
<div class='grid-x grid-padding-x'>
<div class='large-auto cell text-center'>
<a href="https://www.apache.org/">
<img style="height: 60px" title="Apache Software Foundation" src="../../../../../../_/images/asf_logo_wide.svg" />
</a>
</div>
<div class='large-auto cell text-center'>
<a href="https://www.apache.org/events/current-event.html">
<img style="width:234px; height: 60px;" title="Apache Software Foundation current event" src="https://www.apache.org/events/current-event-234x60.png"/>
</a>
</div>
</div>
</div>
<footer>
<div class="grid-container">
<div class="grid-x grid-padding-x">
<div class="large-auto cell">
<h1><a href="../../../../../../front/main/about">About</a></h1>
<ul>
<li><a href="../../../../../../front/main/community/who">Who's Who</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://www.apache.org/security/">Security</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../../../front/main/community">Community</a></h1>
<ul>
<li><a href="../../../../../../front/main/community/mailing-lists">Mailing lists</a></li>
<li><a href="../../../../../../front/main/community/committer">Becoming a committer</a></li>
<li><a href="../../../../../../front/main/community/events">NetBeans Events</a></li>
<li><a href="https://www.apache.org/events/current-event.html">Apache Events</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../../../front/main/participate">Participate</a></h1>
<ul>
<li><a href="../../../../../../front/main/participate/submit-pr">Submitting Pull Requests</a></li>
<li><a href="../../../../../../front/main/participate/report-issue">Reporting Issues</a></li>
<li><a href="../../../../../../front/main/participate/#documentation">Improving the documentation</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../../../front/main/help">Get Help</a></h1>
<ul>
<li><a href="../../../../../../front/main/help/#documentation">Documentation</a></li>
<li><a href="../../../../../../wiki/main/wiki">Wiki</a></li>
<li><a href="../../../../../../front/main/help/#support">Community Support</a></li>
<li><a href="../../../../../../front/main/help/commercial-support">Commercial Support</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../../../front/main/download">Download</a></h1>
<ul>
<li><a href="../../../../../../front/main/download">Releases</a></li>
<li><a href="https://plugins.netbeans.apache.org/">Plugins</a></li>
<li><a href="../../../../../../front/main/download/#_daily_builds_and_building_from_source">Building from source</a></li>
<li><a href="../../../../../../front/main/download/#_older_releases">Previous releases</a></li>
</ul>
</div>
</div>
</div>
</footer>
<div class='footer-disclaimer'>
<div class="footer-disclaimer-content">
<p>Copyright &copy; 2017-2025 <a href="https://www.apache.org">The Apache Software Foundation</a>.</p>
<p>Licensed under the Apache <a href="https://www.apache.org/licenses/">license</a>, version 2.0</p>
<div style='max-width: 40em; margin: 0 auto'>
<p>Apache, Apache NetBeans, NetBeans, the Apache feather logo and the Apache NetBeans logo are trademarks of <a href="https://www.apache.org">The Apache Software Foundation</a>.</p>
<p>Oracle and Java are registered trademarks of Oracle and/or its affiliates.</p>
<p>The Apache NetBeans website conforms to the <a href="https://privacy.apache.org/policies/privacy-policy-public.html">Apache Software Foundation Privacy Policy</a></p>
</div>
</div>
</div>
<script src="../../../../../../_/js/vendor/lunr.js"></script>
<script src="../../../../../../_/js/search-ui.js" id="search-ui-script" data-site-root-path="../../../../../.." data-snippet-length="100" data-stylesheet="../../../../../../_/css/search.css"></script>
<script async src="../../../../../../search-index.js"></script>
<script src="../../../../../../_/js/vendor/jquery.min.js"></script>
<script src="../../../../../../_/js/vendor/what-input.min.js"></script>
<script src="../../../../../../_/js/vendor/foundation.min.js"></script>
<script src="../../../../../../_/js/vendor/jquery.colorbox-min.js"></script>
<script src="../../../../../../_/js/netbeans.js"></script>
<script>
$(function(){ $(document).foundation(); });
</script>
<script src="../../../../../../_/js/vendor/highlight.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
});
</script>
</body>
</html>