GeezerVison is showing javaee.github.io — The dukeetf2 Example Application
Java Platform, Enterprise Edition (Java EE) 8
The Java EE Tutorial
|
The dukeetf2 Example Application
The dukeetf2 example application, located in the
tut-install`/examples/web/websocket/dukeetf2/` directory, demonstrates
how to use a WebSocket endpoint to provide data updates to web clients.
The example resembles a service that provides periodic updates on the
price and trading volume of an electronically traded fund (ETF).
The following topics are addressed here:
Architecture of the dukeetf2 Sample Application
The dukeetf2 example application consists of a WebSocket endpoint, an
enterprise bean, and an HTML page.
-
The endpoint accepts connections from clients and sends them updates
when new data for price and trading volume becomes available.
-
The enterprise bean updates the price and volume information once
every second.
-
The HTML page uses JavaScript code to connect to the WebSocket
endpoint, parse incoming messages, and update the price and volume
information without reloading the page.
The Endpoint
The WebSocket endpoint is implemented in the ETFEndpoint class, which
stores all connected sessions in a queue and provides a method that the
enterprise bean calls when there is new information available to send:
@ServerEndpoint("/dukeetf")
public class ETFEndpoint {
private static final Logger logger = Logger.getLogger("ETFEndpoint");
/* Queue for all open WebSocket sessions */
static Queue<Session> queue = new ConcurrentLinkedQueue<>();
/* PriceVolumeBean calls this method to send updates */
public static void send(double price, int volume) {
String msg = String.format("%.2f / %d", price, volume);
try {
/* Send updates to all open WebSocket sessions */
for (Session session : queue) {
session.getBasicRemote().sendText(msg);
logger.log(Level.INFO, "Sent: {0}", msg);
}
} catch (IOException e) {
logger.log(Level.INFO, e.toString());
}
}
...
}
The lifecycle methods of the endpoint add and remove sessions to and
from the queue:
@ServerEndpoint("/dukeetf")
public class ETFEndpoint {
...
@OnOpen
public void openConnection(Session session) {
/* Register this connection in the queue */
queue.add(session);
logger.log(Level.INFO, "Connection opened.");
}
@OnClose
public void closedConnection(Session session) {
/* Remove this connection from the queue */
queue.remove(session);
logger.log(Level.INFO, "Connection closed.");
}
@OnError
public void error(Session session, Throwable t) {
/* Remove this connection from the queue */
queue.remove(session);
logger.log(Level.INFO, t.toString());
logger.log(Level.INFO, "Connection error.");
}
}
The Enterprise Bean
The enterprise bean uses the timer service to generate new price and
volume information every second:
@Startup
@Singleton
public class PriceVolumeBean {
/* Use the container's timer service */
@Resource TimerService tservice;
private Random random;
private volatile double price = 100.0;
private volatile int volume = 300000;
private static final Logger logger = Logger.getLogger("PriceVolumeBean");
@PostConstruct
public void init() {
/* Initialize the EJB and create a timer */
logger.log(Level.INFO, "Initializing EJB.");
random = new Random();
tservice.createIntervalTimer(1000, 1000, new TimerConfig());
}
@Timeout
public void timeout() {
/* Adjust price and volume and send updates */
price += 1.0*(random.nextInt(100)-50)/100.0;
volume += random.nextInt(5000) - 2500;
ETFEndpoint.send(price, volume);
}
}
The HTML Page
The HTML page consists of a table and some JavaScript code. The table
contains two fields referenced from JavaScript code:
<!DOCTYPE html>
<html>
<head>...</head>
<body>
...
<table>
...
<td id="price">--.--</td>
...
<td id="volume">--</td>
...
</table>
</body>
</html>
The JavaScript code uses the WebSocket API to connect to the server
endpoint and to designate a callback method for incoming messages. The
callback method updates the page with the new information.
var wsocket;
function connect() {
wsocket = new WebSocket("ws://localhost:8080/dukeetf2/dukeetf");
wsocket.onmessage = onMessage;
}
function onMessage(evt) {
var arraypv = evt.data.split("/");
document.getElementById("price").innerHTML = arraypv[0];
document.getElementById("volume").innerHTML = arraypv[1];
}
window.addEventListener("load", connect, false);
The WebSocket API is supported by most modern browsers, and it is widely
used in HTML5 web client development.
Running the dukeetf2 Example Application
This section describes how to run the dukeetf2 example application
using NetBeans IDE and from the command line.
The following topics are addressed here:
To Run the dukeetf2 Example Application Using NetBeans IDE
-
Make sure that GlassFish Server has been started (see
Starting and Stopping GlassFish
Server).
-
From the File menu, choose Open Project.
-
In the Open Project dialog box, navigate to:
tut-install/examples/web/websocket
-
Select the dukeetf2 folder.
-
Click Open Project.
-
In the Projects tab, right-click the dukeetf2 project and select
Run.
This command builds and packages the application into a WAR file
(dukeetf2.war) located in the target/ directory, deploys it to the
server, and launches a web browser window with the following URL:
http://localhost:8080/dukeetf2/
Open the same URL on a different web browser tab or window to see how
both pages get price and volume updates simultaneously.
To Run the dukeetf2 Example Application Using Maven
-
Make sure that GlassFish Server has been started (see
Starting and Stopping GlassFish
Server).
-
In a terminal window, go to:
tut-install/examples/web/websocket/dukeetf2/
-
Enter the following command to deploy the application:
-
Open a web browser window and enter the following URL:
http://localhost:8080/dukeetf2/
Open the same URL on a different web browser tab or window to see how
both pages get price and volume updates simultaneously.
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.
|