Post on 16-Apr-2017
Java on Azure
Azure WebSocket
Web Apps
Version: 1.0 Last updated: 2015/12/22
2
....................................................................................................................................................... 3 ................................................................................................................................................ 3 1 : WebSocket ...................................................................................................................... 4 2 : WebSocket ............................................. 8 Microsoft Azure .................................................................................... 8 WebSocket ................................................................................................. 11 WebSocket .................................................................................. 22 3 : WebSocket ............................................................... 35 WebSocket ................................................................................................. 35 WebSocket .................................................................................. 47 4 : ............................................................................................................................. 52
3
Microsoft Azure Web (PaaS) (IaaS) Microsoft Azure PaaS Web Apps WebSocket WebSocket JSON Java
WebSocket
WebSocket
WebSocket
6090
4
1 : WebSocket
WebSocket W3C IETF W3C API IETF WebSocket HTTP WebSocket Web (HTTP )Web Web Internet Explorer Microsoft Edge (Windows 10 )FirroxSafari Web http:// URL
Web (HTTP )
Web
5
HTML
Web Web Web
Ajax JavaScript
Web polling Web Reverse Ajax(Comet)Reverse Ajax (Comet) Web Streaming Long-Polling
Web
6
Reverse Ajax(Comet) Web Reverse Ajax Web HTTP HTTP (HTTP )Web Web API (HTTP ) Web (HTTP ) HTTP WebSocket W3C IETF Web
Web Web WebSocket WebSocket
WebSocket WebSocket
7
WebSocket
8
2 : WebSocket
WebSocket
Microsoft Azure
1,2 3, 4 Microsoft Azure 3, 4
1. DreamSpark http://yoshio3.com/2015/10/13/about-dreamspark-program/ 2. Microsoft Azure for DreamSpark http://yoshio3.com/2015/10/14/config-azure-for-dreamspark/
3. Java Web (JDK&NetBeans ) http://yoshio3.com/2015/10/15/prepare-java-dev-env/ 4. Microsoft Azure Web App NetBeans (Maven) FTP http://yoshio3.com/2015/10/16/config-ftp-4-azure-netbeans/
9
4. Microsoft Azure App ServiceWebSocketWebSocket Microsoft Azure App Service App Service
10
Web
11
WebSocket
WebSocket WebSocket HTML JavaScript HTML JavaScript WebSocket
index.html HTML
12
WebSocket WebSocket
13
HTML JavaScript Web jsjsWeb
(C):(F): >
14
15
(N):js(F)
16
Web js
jswebsocket-chat.jsJavaScript js
17
(C):(F):JavaScript >
18
(N):websocket-chat
19
jswebsocket-chat.jswebsocket-chat.js
JavaScript var websocket = null; var username = null; if (window.addEventListener) { //for W3C DOM window.addEventListener("load", init, false); } else if (window.attachEvent) { //for IE
20
window.attachEvent("onload", init); } else { window.onload = init; } /* */ function init() { showLoginButton(); } /* */ function connectServerEndpoint() { var wsUri = "ws://" + document.location.hostname + ":" + document.location.port + document.location.pathname + "chat-server"; // FireFox if ("WebSocket" in window) { websocket = new WebSocket(wsUri); } else if ("MozWebSocket" in window) { websocket = new MozWebSocket(wsUri); } websocket.onopen = function (evt) { showLogoutButton(); }; websocket.onmessage = function (evt) { ; }; websocket.onerror = function (evt) { console.log("WebSocket Error : " + evt); }; websocket.onclose = function (evt) { closeServerEndpoint(); }; }
21
/* */ function closeServerEndpoint() { websocket.close(4001, "Close connection from client"); showLoginButton(); } /* () */ function showLoginButton() { document.getElementById("login").style.display = "block"; document.getElementById("logout").style.display = "none"; } /* () */ function showLogoutButton() { document.getElementById("login").style.display = "none"; document.getElementById("logout").style.display = "block"; }
22
WebSocket
WebSocket
pom.xml slf4j pom.xml
4.0.0
23
com.yoshio3 Azure-Jetty9-WebSocket-JSF 1.0-SNAPSHOT war Azure-Jetty9-WebSocket-Chat ${project.build.directory}/endorsed UTF-8 javax javaee-web-api 7.0 provided javax.websocket javax.websocket-api 1.0 provided org.slf4j slf4j-api 1.7.10 org.slf4j slf4j-simple 1.7.10
24
org.apache.maven.wagon wagon-ftp 1.0-beta-3 org.mortbay.jetty jetty-maven-plugin 9.1.0.v20131115 org.codehaus.mojo wagon-maven-plugin 1.0-beta-3 upload-war install upload ${basedir}/target ${project.build.finalName}.war ftp://waws-prod-os1-001.ftp.azurewebsites.windows.net /site/wwwroot/webapps/ ftp-repository
25
org.apache.maven.plugins maven-compiler-plugin 3.1 1.7 1.7 ${endorsed.dir} org.apache.maven.plugins maven-war-plugin 2.3 false org.apache.maven.plugins maven-dependency-plugin 2.6 validate copy ${endorsed.dir} true
26
javax javaee-endorsed-api 7.0 jar
log4j Azure-Jetty9-WebSocket-Chat
27
log4j WebSocket Azure-Jetty9-WebSocket-ChatJava Java (C):Java(F):Java
28
(N):ChatServerEndpoint(F)
Java @ServerEndpoint(value = "/chat-server") public class ChatServerEndpoint { // private final static org.slf4j.Logger logger = LoggerFactory.getLogger(ChatServerEndpoint.class); // Jetty // private static final Set< Session> sessions = Collections.synchronizedSet(new HashSet()); @OnOpen public void onOpen(Session session) throws IOException { logger.info("onOpen: " + session.getId()); sessions.add(session);
29
logger.info("onOpen Number of sessions: " + sessions.size()); } @OnClose public void onClose(Session session) throws IOException { logger.info("onClose: " + session.getId()); sessions.remove(session); logger.info("onClose Number of sessions: " + sessions.size()); } @OnError public void onError(Throwable p) { logger.error("WebSocket onError : ", p); } }
Azure-Jetty9-WebSocket-Chat
Microsoft Azure FTP BUILD SUCCESS
30
Microsoft Azure Web
31
()Web
Web URL
32
URL http://*****-*****.azurewebsites.net/Azure-Jetty9-WebSocket-Chat
$ ftp waws-prod-os1-001.ftp.azurewebsites.windows.net Trying 138.91.24.26... Connected to waws-prod-os1-001.drip.azurewebsites.windows.net. 220 Microsoft FTP Service
33
Name (waws-prod-os1-001.ftp.azurewebsites.windows.net:yoterada): yosshi2007-jettyyosshi2007-dep 331 Password required Password: 230 User logged in. Remote system type is Windows_NT. ftp> ls 229 Entering Extended Passive Mode (|||10083|) 125 Data connection already open; Transfer starting. 10-22-15 11:54AM LogFiles 10-22-15 11:03AM site 226 Transfer complete. ftp> cd LogFiles 250 CWD command successful. ftp> ls 229 Entering Extended Passive Mode (|||10085|) 125 Data connection already open; Transfer starting. 10-22-15 11:40AM DetailedErrors 10-22-15 11:55AM 4655 eventlog.xml 10-22-15 11:04AM http 10-22-15 11:55AM 0 jetty_2015_10_22.stderrout.log 10-22-15 11:03AM kudu 10-22-15 11:16AM SiteExtensions 10-22-15 11:40AM W3SVC647188608 226 Transfer complete. ftp>
34
ftp> ls 229 Entering Extended Passive Mode (|||10094|) 125 Data connection already open; Transfer starting. 10-22-15 11:40AM DetailedErrors 10-22-15 11:55AM 4655 eventlog.xml 10-22-15 11:04AM http 10-22-15 11:57AM 0 jetty_2015_10_22.stderrout.log 10-22-15 11:55AM 1485 jetty_2015_10_22.stderrout.log.115749862 10-22-15 11:03AM kudu 10-22-15 11:16AM SiteExtensions 10-22-15 11:40AM W3SVC647188608 226 Transfer complete. ftp> get jetty_2015_10_22.stderrout.log.115749862 local: jetty_2015_10_22.stderrout.log.115749862 remote: jetty_2015_10_22.stderrout.log.115749862 229 Entering Extended Passive Mode (|||10093|) 125 Data connection already open; Transfer starting. 100% |****************************************************************************************| 1485 93.97 KiB/s 00:00 ETA 226 Transfer complete. 1485 bytes received in 00:00 (62.74 KiB/s) ftp> quit 221 Goodbye.
2015-10-22 11:55:23.848:INFO:oejs.Server:main: jetty-9.1.0.v20131115 2015-10-22 11:55:23.895:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:/D:/home/site/wwwroot/webapps/] at interval 1 2015-10-22 11:55:25.192:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@1fcfece{/Azure-Jetty9-WebSocket-JSF,file:/D:/local/Temp/jetty-127.0.0.1-17537-Azure-Jetty9-WebSocket-JSF-1.0-SNAPSHOT.war-_Azure-Jetty9-WebSocket-JSF-1.0-SNAPSHOT-any-2705390846338938535.dir/webapp/,AVAILABLE}{D:homesitewwwrootwebappsAzure-Jetty9-WebSocket-JSF-1.0-SNAPSHOT.war}
35
2015-10-22 11:55:25.301:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@4718df{/,file:/D:/home/site/wwwroot/webapps/ROOT/,AVAILABLE}{D:homesitewwwrootwebappsROOT} 2015-10-22 11:55:25.411:INFO:oejs.ServerConnector:main: Started ServerConnector@1dc3715{HTTP/1.1}{127.0.0.1:17537} [qtp26111414-61] INFO com.yoshio3.ChatServerEndpoint - onOpen: websocket-1 [qtp26111414-58] INFO com.yoshio3.ChatServerEndpoint - onClose: websocket-1 [qtp26111414-62] INFO com.yoshio3.ChatServerEndpoint - onOpen: websocket-2 [qtp26111414-61] INFO com.yoshio3.ChatServerEndpoint - onClose: websocket-2 [qtp26111414-58] INFO com.yoshio3.ChatServerEndpoint - onOpen: websocket-3 [qtp26111414-62] INFO com.yoshio3.ChatServerEndpoint - onClose: websocket-3 [qtp26111414-61] INFO com.yoshio3.ChatServerEndpoint - onOpen: websocket-4 [qtp26111414-58] INFO com.yoshio3.ChatServerEndpoint - onClose: websocket-4
FTP
3 : WebSocket
WebSocket WebSocket
WebSocket
Connect
36
WebSocket
37
index.html HTML WebSocket WebSocket
38
websocket-chat.js JavaScript WebSocket
39
JavaScript websocket-chat.js var websocket = null; var username = null; if (window.addEventListener) { //for W3C DOM window.addEventListener("load", init, false); } else if (window.attachEvent) { //for IE window.attachEvent("onload", init); } else { window.onload = init; } /* */ function init() { // chat showLoginButton(); } /* */ function connectServerEndpoint() { var wsUri = "ws://" + document.location.hostname + ":"
40
+ document.location.port + document.location.pathname + "chat-server"; // FireFox if ("WebSocket" in window) { websocket = new WebSocket(wsUri); } else if ("MozWebSocket" in window) { websocket = new MozWebSocket(wsUri); } //Chat ) showChatMessage(); websocket.onopen = function (evt) { username = document.getElementById("name").value; sendMessage(username + " "); }; websocket.onmessage = function (evt) { writeToScreen(evt); }; websocket.onerror = function (evt) { console.log("WebSocket Error : " + evt); }; websocket.onclose = function (evt) { closeServerEndpoint(); }; } /* */ function closeServerEndpoint() { sendMessage(username + " "); websocket.close(4001, "Close connection from client"); showLoginButton(); } /* */ function sendMessage(message) { websocket.send(message); } /* */
41
function submitMessage() { msg = document.getElementById("inputMessage").value; sendMessage(username + " : " + msg); } /* */ function writeToScreen(evt) { var element = document.createElement('div'); element.className = "message"; element.textContent = evt.data; element.style.backgroundColor = "white"; // var objBody = document.getElementById("insertpos"); objBody.insertBefore(element, objBody.firstChild); // bodydiv } /* () */ function showLoginButton() { document.getElementById("login").style.display = "block"; document.getElementById("chat").style.display = "none"; } /* () */ function showChatMessage() { document.getElementById("login").style.display = "none"; document.getElementById("chat").style.display = "block"; }
JavaScript WebSocket var websocket = null; var username = null; websocket.onopen = function (evt) { username = document.getElementById("name").value; sendMessage(username + " "); }; /* */
42
function sendMessage(message) { websocket.send(message); }
document.getElementById("name").value sendMessage()sendMessage() WebSocket username //Chat ) showChatMessage(); /* () */ function showChatMessage() { document.getElementById("login").style.display = "none"; document.getElementById("chat").style.display = "block"; }
WebSocket showChatMessage()
(none)(block) /* */ function submitMessage() { msg = document.getElementById("inputMessage").value; sendMessage(username + " : " + msg); }
submitMessage()username : WebSocket /* */ function closeServerEndpoint() { sendMessage(username + " "); websocket.close(4001, "Close connection from client");
43
showLoginButton(); }
WebSocket closeServerEndpoint()username WebSocket websocket.onmessage = function (evt) { writeToScreen(evt); }; /* */ function writeToScreen(evt) { var element = document.createElement('div'); element.className = "message"; element.textContent = evt.data; element.style.backgroundColor = "white"; // var objBody = document.getElementById("insertpos"); objBody.insertBefore(element, objBody.firstChild); // bodydiv }
WebSocket JavaScript websocket.onmessage()onmessage()writeToScreen() writeToScreen()(objBody.firstChild)(insertBefore)writeToScreen() HTML :
CSS
44
NetBeans Web
(N):css(F)
css
45
(C):HTML5(F):Cascading Style Sheet >
46
(N):ws-chat(F)
ws-chat.css /* To change this license header, choose License Headers in Project Properties. To change this template file, choose Tools | Templates and open the template in the editor. */ /* Created on : 2015/11/10, 16:11:05 Author : Yoshio Terada */ .title{ position:relative; margin:0 auto; width:480px; overflow:hidden;
47
} .login{ position:relative; margin:0 auto; width:480px; overflow:hidden; } .chat{ position:relative; margin:0 auto; width:480px; overflow:hidden; } .chat .messages{ width:100%; height:480px; overflow:hidden; } .chat .messages:hover{ overflow-y:scroll; } .chat .messages > div{ padding:15px; border-bottom:1px dashed #999; }
WebSocket
WebSocket
WebSocket onMessage()onMessage() /* * Copyright 2015 Yoshio Terada *
48
* Licensed 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. */ package com.yoshio3; import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; /** * * @author Yoshio Terada */ @ServerEndpoint(value = "/chat-server") public class ChatServerEndpoint { // Jetty private static final Set< Session> sessions = Collections.synchronizedSet(new HashSet()); @OnOpen
49
public void onOpen(Session session) throws IOException { sessions.add(session); } @OnMessage public void onMessage(String message, Session session) throws IOException { //Jetty 9.1.0.v20131115 Java SE 8 //Java SE 7 (Lambda ) //Jetty //Set sessions = session.getOpenSessions(); // null NullPointerException // //https://bugs.eclipse.org/bugs/show_bug.cgi?id=422192 for (Session sess : sessions) { if (sess.isOpen()) { sess.getBasicRemote().sendText(message); } } } @OnClose public void onClose(Session session) throws IOException { sessions.remove(session); } @OnError public void onError(Throwable p) { System.out.println("onError " + p.getMessage()); } }
Set sessions sess.getBasicRemote().sendText(message)
50
Azure-Jetty9-WebSocket-Chat
Microsoft Azure FTP BUILD SUCCESS
Web URL http://*****-*****.azurewebsites.net/Azure-Jetty9-WebSocket-Chat URL WebSocket
51
52
WebSocket WebSocket
4 :
WebSocket RFC 6455 WebSocket Protocol https://tools.ietf.org/html/rfc6455 W3C The WebSocket API http://www.w3.org/TR/2011/WD-websockets-20110929/ JSR 356: Java API for WebSocket https://jcp.org/en/jsr/detail?id=356 Java EE 7 WebSocket SlideShare Java EE 7 Detail http://www.slideshare.net/OracleMiddleJP/java-ee-7-detail/142 SlideShare Java EE 7 http://yoshio3.com/2013/10/23/java-ee-7-hol-on-jjug-ccc/ Twitter http://yoshio3.com/2012/11/12/websocket-twitter-timeline-sample/ WebSocket Mailer http://yoshio3.com/2013/12/20/java-ee-7-websocket-anti-pattern/