狠狠撸

狠狠撸Share a Scribd company logo
? 2013 IBM Corporation
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
いよいよ始められる
Java ?EEでのWebSocket
1
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Agenda
§??Java ?EE ?7とHTML5
§??WebSocketとは
§??WebSocketの現状
§??Java ?EEでのWebSocketアプリ開発
2
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Java ?EE ?7とHTML5
3
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Java EE 7の三つのゴール
§??HTML5環境への対応
§??開発?生産性の向上
§??エンタープライズ?ニーズへの対応
4
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
三つのゴールとJava ?EE仕様群との対応
§??HTML5環境への対応
–? JSR 344: JavaServer Faces (JSF) 2.2
–? JSR 353: Java API for JSON Processing (JSONP) 1.0
–? JSR 356: Java API for WebSocket 1.0
–? JSR 339: Java API for RESTful Web Services (JAX-RS) 2.0
§??開発?生産性の向上
–? JSR 345: Enterprise JavaBeans (EJB) 3.2
–? JSR 346: Contexts and Dependency Injection
for Java EE (CDI) 1.1
–? JSR 907: Java Transaction API (JTA) 1.2
–? JSR 349: Bean Validation 1.1
§??エンタープライズ?ニーズへの対応
–? JSR 343: Java Message Service (JMS) 2.0
–? JSR 338: Java Persistence API (JPA) 2.1
–? JSR 236: Concurrency Utilities for Java EE 1.0
–? JSR 352: Batch Applications for the Java Platform 1.0
5
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
2014年年10?月 ?ついに正式勧告となったHTML5
§??従来のHTML
–?画面をレンダリングするための規格	
§??HTML5(+ ?CSS3 / JavaScript)
–?アプリケーションを記述するための規格	
6
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
HTML5環境の新しいアプリケーションスタイル
§??「サーバーサイドMVC」から「クライアントMVC」へ
7
Web Browser
Application Server
Application
HTTP
Request
HTML/JS
Controller Session
Data
View
Business
LogicModel
DomainDomain
Web Browser
Application Server
Application
View
HTML/JS
Controller
Data
Store
Model
Model
DomainDomain
RESTful or
WebSocket
JSON
Business Logic
従来のWebアプリケーション Single Page Application (SPA)
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
HTML5におけるクライアント?サーバー連携
§??通信?方法
–?RESTful (JAX-RS 2.0)
?? HTTPの原則にしたがった
簡潔なシステム間連携の設計手法
–?WebSocket (WebSocket 1.0)
?? ブラウザとWebサーバーの間で
双方向通信を可能にする
通信プロトコル
§??データ型
–?JSON:JavaScript Object Notation
(JSONP 1.0)
?? JavaScriptのオブジェクトとして
そのままパースできる
テキスト形式のデータ表記法	
8
Web Browser
Application Server
Application
View
HTML/JS
Controller
Data
Store
Model
Model
DomainDomain
RESTful or
Web Socket
JSON
Business Logic
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
HTTP通信によるサーバー連携の問題点
§??基本的に半?二重通信
–?ひとつのHTTPのセッションで
「?一回のリクエスト」と「?一回のレスポンス」
–?Keep ?Aliveにより複数のセッションを
?一つのTCPコネクションで繰り返すことは可能
§??サーバーのイベントをトリガーとした通信が困難
–?リクエストの送信はクライアントからだけ
§??通信が冗??長
–?リクエスト?レスポンス毎に多くのヘッダ情報
9
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
従来のブラウザとの双?方向通信
§??従来のWeb技術で双?方向通信を実現するには
Comet技術などで無理理?矢理理,実現していた
–?サーバーはリクエストの応答を返さずにイベントが発生するまで待機
10
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
新しい双?方向通信:WebSocket
§??WebSocketを使?用すると双?方向通信を?自然な形で実現
–?HTTPで通信を開始して,
Protocol SwitchingによりWebSocketに移行
–?サーバー側からもクライアント側からもメッセージを送信可能
11
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocket ?URI
§??URIスキームとして以下を使?用する
–?ws://
 ? ? ? ?WebSocketによるNon-‐??SSL通信(80ポート)
–?wss://
 ? ? ? ?WebSocketによるSSL通信(443ポート)
§??httpと同様に80/443ポートを使?用するため
多くの環境でFirewallの追加設定は不不要
12
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocketのハンドシェイク
§??HTTPでWebSocketのハンドシェイクを?行行う
13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat (オプション)
Sec-WebSocket-Version: 13
HTTP GETリクエストでOpening Handshakeを送信
ステータスコード101を返してWebSocketにプロトコルスイッチ
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocketのライフサイクル
14
WebSocketの接続状態
CONNECTING
OPEN
CLOSING
CLOSED
Opening Handshake
Closing Handshake
データの送受信
?
?
?
TCP接続の切断
クライアント サーバー
TCP接続の確立
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocketの?用語
§??WebSocketエンドポイント ?(endpoint)
§?? WebSocketの確?立立された接続の両端をうけもつ2つのコンポーネント
§??クライアントエンドポイントとサーバーエンドポイント
(client ?endpoint ?and ?server ?endpoint)
§?? 接続を開始した側のエンドポイントと,
接続を待ち受けていた側のエンドポイント
§??ピア ?(peer)
§?? 接続している相?手側のエンドポイント
§??WebSocketセッション ?(session)
§?? ?二つのエンドポイントの間で確?立立されている通信セッション
15
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
既存技術との?比較
§??Ajax
–?定期的にポーリング
–?最?大でポーリング間隔の
タイムラグが発?生する
–?あまりポーリング間隔を
短くするとサーバーに負荷が
16
§??Comet
–?イベントが発?生するまで
応答を遅延させる
–?クライアントからの
イベント通知には不不向き
HTML
JS
クライアント サーバー
CSS
Data#2
Data#1画面遷移
Dataなし
Data#3
HTML
JS
クライアント サーバー
CSSData#1画面遷移
イベン
ト発生
待機
イベン
ト発生
待機
Data#2
Data#3
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocketのメリット
§??双?方向リアルタイム通信における技術的な課題を解決
17
比較項目 Ajax Comet WebSocket
使用プロトコル HTTP HTTP WebSocket(ハンドシェイ
ク時にHTTPを利用)
1回のTCP接続で可能
なデータ取得回数(*)
1回
(要求/応答の1往復)
1回
(要求/応答の1往復)
複数回
クライアントからの
Pull型データ取得
可能 可能 可能
サーバーからの
Push型データ配信
不可能 ロングポーリングによる
擬似的Push配信
可能
リアルタイム通信 不向き
(ポーリングが必要)
ロングポーリングによる
擬似的リアルタイム通信
可能
HTTPヘッダーの
オーバーヘッド
あり あり なし
TCPハンドシェイクに
よるオーバーヘッド
あり(*) あり(*) なし
(*)HTTP KeepAliveを使用しない場合
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocketの現状
18
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocket プロトコルの現状
§??プロトコルはIETF / RFCで標準化
–?2010年年2?月? draft-hixie-thewebsocketprotocol-75
–?2010年年5?月? draft-ietf-hybi-thewebsocketprotocol-00
–?2011年年4?月? draft-ietf-hybi-thewebsocketprotocol-07
–?2011年年7?月? draft-ietf-hybi-thewebsocketprotocol-10
–?2011年年12?月? RFC 6455 "The WebSocket Protocol"
§??W3CでJavaScript APIを仕様化
–?2009年年4?月? First Public Draft
–?2009年年10?月?~2012年年8?月? Working Draft
–?2012年年9?月 W3C Candidate Recommendation
19
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
ブラウザの対応状況
20
§??モダンなブラウザの?大部分がサポート
MSIE
10 (2013/2) ?~
Chrome
16 (2011/12) ?~
Firefox
11 (2012/3) ?~
Safari
6 (2012/7) ?~
iOS
6.0 (2012/9) ?~
Android
4.4 (2013/10) ?~
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
対応ブラウザのシェア
21
§??70%以上のブラウザがWebSocketに対応
出典:NetMarketShare.com Market Share Reports October, 2014
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
商?用Java ?EEサーバーでもサポートが開始
§??2014年年7?月? Oracle ?WebLogic ?Server ?12.1.3で対応
§??2014年年12?月 ?IBM ?WebSphere ?Application ?Server ?8.5.5
?  ?   ?Libertyプロファイルで対応
22
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Webサーバー?プラグインの対応
§??IBM ?HTTP ?Server(IHS)
–?2014年年8?月 ?IHS ?/ ?WAS ?Plug-‐??in ?8.5.5.3で対応
§??Load ?Balancer
–?WAS ?NDに同梱のLoad ?BalancerもWebSocketのふりわけが可能
–?F5 ?BIG-‐??IPなどもアプライアンス製品もWebSocketに対応
 ?  ? コネクション数の上限には注意
23
WAS
WAS
IHS Plug-in
IHS Plug-in
? 
Load
Balancer
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
クライアント側にProxyがある場合
§??WebSocketのリクエストはCONNECTメソッドで開始
§??TLS ?/ ?SSLが正常につかえる環境であればOK
§??すでにAjax ?/ ?Cometが多数普及しているため
??長時間のコネクションへの対応は済んでいる(はず)
24
_Proxy Usage_: If the client is configured to use a proxy when using the WebSocket Protocol to
connect to host /host/ and port /port/, then the client SHOULD connect to that proxy and ask it to
open a TCP connection to the host given by /host/ and the port given by /port/.
EXAMPLE: For example, if the client uses an HTTP proxy for all traffic, then if it was to try to
connect to port 80 on server example.com, it might send the following lines to the proxy
server:
CONNECT example.com:80 HTTP/1.1
Host: example.com
RFC 6455
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Java ?EEでの
WebSocketアプリ開発 ?
25
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
JSR ?356: ?Java ?API ?for ?WebSocket ?1.0 ?
§??JavaでWebSocket通信を実装するためのAPI
§??クライアントとサーバーの両?方をサポート
§??Java ?SE環境での実?行行も考慮された仕様
§??アノテーションをベースとした
モダンなプログラミングスタイル
§??Encoder ?/ ?Decoderにより
扱うデータ型を柔軟に制御
26
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Endpoint:ServerEndpointとClientEndpoint
§??WebSocket通信の両端となるEndpointの作成が必須
–?WebSocket通信の開始?終了了?エラー発?生と
メッセージ受信をトリガーにEndpointのメソッドが呼び出される
§??クライアントはブラウザで実装することが多いので,
多くの場合Java ?EEではサーバー側のEndpointを実装する
27
ClientEndpoint ServerEndpoint
Session @OnMessage
public void message(... )
@OnOpen
public void open(... )
@OnClose
public void close(... )
@OnMessage
public void message(... )
@OnError
public void error(... )
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Endpointの作成
§???二つの実装?方法
–?アノテーションをつけたPOJO
??@javax.websocket.server.ServerEndpoint
??@javax.websocket.ClientEndpoint
–?javax.websocket.Endpointを継承したクラス
アノテーションベースのPOJOで実装するほうが簡単
28
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
アノテーションによるEndpoint実装の例例
29
@ServerEndpoint("/echo")?
public class EchoServiceEndpoint{	
Session currentSession = null;	
//接続がオープンしたとき?
@OnOpen?
public void onOpen(Session session, EndpointConfig ec) {?
currentSession = session;?
}	
//メッセージを受信したとき?
@OnMessage?
public void receiveMessage(String msg) throws IOException {?
//メッセージをクライアントに送信する?
currentSession.getBasicRemote().sendText("Hello" + msg);?
}	
//接続がクローズしたとき?
@OnClose?
public void onClose(Session session, CloseReason reason) { ??? ?}	
//接続エラーが発?生したとき?
@OnError?
public void onError(Throwable t) {??? ?}	
}
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocket ?1.0で定義されているアノテーション
§?? @ServerEndpoint ?/ ?@ClientEndpoint
–?サーバー側 ?/ ?クライアント側のエンドポイント
§?? @OnOpen ?/ ?@OnMessage ?/ ?@OnError ?/ ?@OnClose
–?ライフサイクルのイベントで呼び出されるメソッド
§?? @PathPram
–? リクエストURIのパスの?一部をパラメーターとして受け取る
30
アノテーション イベント 例
@OnOpen 接続がオープンしたとき @OnOpen
Public void open(Session session, EndpointConfig conf) {}
@OnMessage メッセージを受信したとき @OnMessage
Public void message(Session session, String msg) {}
@OnError 接続エラーが発生したとき @OnError
public void error(Session session, Throwable error) {}
@OnClose 接続がクローズしたとき @OnClose
Public void close(Session session, CloseReason reason) {}
@ServerEndpoint(value = “/sample/{name}”)
Public class SampleEndpoint {
@OnOpen
public void open(Session session,EndpointConfig ec, @PathParam("name") String name) { ??? }
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
JVMJVM
Endpointのインスタンス
§??Endpointのインスタンスは
WebSocketのセッションごとに別個に作成される
–?Servletのインスタンスが,サーバーに?一つ作成されて
複数のリクエスト?セッションで共有されるのと対照的
31
Endpoint
インスタンス
Servlet
インスタンス
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Endpointのコーディング(1)
§??セッションの情報をインスタンス変数に保存できる
–?多くの場合,javax.websocket.Sessionの保存は必須
§??「時間のかかる初期化処理理」はEndpoint毎には書かない
–?@Singletonの@EJBなどに実装しておいて呼び出す
32
@ServerEndpoint(value = "/echo")	
public class EchoServiceEndpoing {	
private Session currentSession;	
@OnOpen	
public void onOpen(Session session, EndpointConfig ec) {	
currentSession = session;
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Endpointのコーディング(2)
§??マルチスレッドを考える必要はない
–?それぞれのインスタンスの@OnOpenメソッドなどが
複数スレッドから同時に呼ばれることはない
–?ただし複数のEndpoint ?/ ?Sessionにまたがる処理理では,
状況に応じて排他制御が必要
33
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
ピアへのメッセージの送信
§??SessionからRemoteEndpointを取得して使?用する
§??RemoteEndpointは,2種類
–?RemoteEndpoint.Async ?非同期通信
–?RemoteEndpoint.Basic 同期通信
§??Sessionは
他のスレッドで稼働しているServlet ?/ ?EJBからも利利?用可能
–?複数スレッドから?一つのSessionを同時に利利?用することは避ける
34
if (session.isOpen())?
session.getBasicRemote().sendText(msg);
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Encoder ?/ ?Decoder
§??ピアとの間で送受信するのは?文字列列かバイナリ
§??変換をおこなうEncoder ?/ ?Decoderをおくことで
エンドポイントからJavaのオブジェクトで
送受信することができる
35
ServerEndpoint
@OnMessage
public void message(... )
@OnOpen
public void open(... )
@OnClose
public void close(... )
Decoder	
Encoder	
String / byte列列
Javaの
オブジェクト
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Decoder ?/ ?Encoder ?の実装と利利?用
§??インターフェースをimplementsする
§??@ServerEndpoint ?/ ?@ClientEndpoint ?に追記
36
class MyObjectDecoder implements Decoder.Binary<MyObject> {	
	@Override	
	public boolean willDecode(ByteBuffer buf) {	
	 	...	
	}	
	@Override	
	public MyObject decode(ByteBuffer arg0) throws DecodeException {	
	 	...	
	}
@ServerEndpoint(value = "/chat", decoders = MyObjectDecoder.class)	
public class ChatService {
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
HTTPヘッダ?HttpSessionへのアクセス
§??Con?guratorのmodifyHandshakeメソッドを利利?用する
–?HandshakeRequestからHTTPヘッダやHttpSessionが取得できる ?
§??@ServerEndpoint ?/ ?@ClientEndpoint ?に追記
37
import javax.websocket.server.ServerEndpointConfig.Configurator;	
	
public class ChatConfig extends Configurator {	
	@Override	
	public void modifyHandshake(ServerEndpointConfig sec,?
	 	HandshakeRequest req,?
	 	HandshakeResponse resp) {	
@ServerEndpoint(value = "/chat", configurator = ChatConfig.class)	
public class ChatService {
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Con?guratorからEndpointへの情報伝達
§??EndpointCon?gのUserPropertiesを利利?用する
38
public void modifyHandshake(ServerEndpointConfig config,?
	HandshakeRequest req, HandshakeResponse resp) {?
?
HttpSession session = (HttpSession)request.getHttpSession();?
Map<String,Object> userProps = config.getUserProperties();?
userProps.put("MyID", ?
(session != null)? session.getAttribute("MyID") : "No ID");	
@OnOpen	
public void onOpen(Session session, EndpointConfig config) {	
?
Map<String,Object> userProps = config.getUserProperties();	
String myID = (String)userProps.get("MyID");	
Configurator
Endpoint
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Con?guratorやEndpointでHttpSessionを書き換えない
§??HandshakeRequestからHttpSessionは取得できるが,
Attributeのセット?更更新?削除は危険
–?分散環境では,HttpSessionの内容は複数サーバー間で共有される
–?多くのアプリケーションサーバーでは,サーバー間の
HttpSession情報の更更新はリクエスト処理理が完了了した時に実?行行
–?WebSocketでは,セッションが短時間で終了了しない
→ ?変更更内容が他のサーバーになかなか伝搬しない
§??Con?guratorでは,
HttpSessionから読み取りのみをおこなうのが安全
39
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
さらに詳細に知りたい場合は
§??IBM ?developerWorksでWebSocketを検索索
40
Java EE 7 アプリケーション設計ガイド ?– WebSocket編
http://www.ibm.com/developerworks/jp/websphere/library/was/javaee7_appguide/1.html
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
いますぐ
WebSocketを試すには
41
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WASの新しいランタイム:Libertyプロファイル
42
WAS V8.5.5 Liberty & WDT
Web Profile準拠
Java EE 6のWeb Profile標準に
準拠したアプリを完全サポート
JAX-WS, JAX-RS, JMSもサポート
Unzipによる導?入とデプロイ
パッケージをした
サーバー ?+ アプリ ?+ 構成情報を
Unzipでデプロイ可能
簡単な構成と動的変更更
最低限必要な構成ファイルは
server.xmlひとつだけ
デフォルトベースで簡単構成
構成変更更は再起動なしに反映
軽量量ランタイム
メモリー使?用量量が?小さい: 60MB程度度?~
ディスク使?用量量も100MB以下
起動が速い
起動時間: 5秒程度度
統合ツール(WDT)
?高機能なEclipse?用の連携ツールを無償で提供
Eclipseから簡単に使?用可能
?自動化ツールとの連携
多くのOSSツールに
無償でプラグインを提供
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
API?サーバー機能をFeatureとして定義
§??必要なものだけを構成 ?
–?設定されたものだけがメモリにロード?初期化される
→ ?最?小限の起動時間?メモリー使?用
43
ServletJSPJDBCSSL
JAX-RS
sessionDatabase
<featureManager>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>jsp-?‐2.2</feature>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>jdbc-?‐4.0</feature>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>jaxrs-?‐1.1</feature>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>sessionDatabase-?‐1.0</feature>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>ssl-?‐1.0</feature>	
 ?
</featureManager>	
 ?
構成ファイル ?server.xml
依存関係も
?自動的に解決
JSON
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
WebSocketにも対応したBeta版を無償公開中
§??現在,Java ?EE ?7の?一部の機能を実装した
LibertyプロファイルをBetaとして公開
§??websocket-‐??1.0フィーチャーを有効にすれば
WebSocketアプリケーションを実?行行可能
44
<featureManager>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>jsp-?‐2.2</feature>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>jdbc-?‐4.0</feature>	
 ?
	
 ?	
 ?	
 ?	
 ?<feature>websocket-?‐1.0</feature>	
 ?
</featureManager>	
 ?
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
Eclipseにマーケットプレースから開発者ツールを導?入
§??メニューからヘルプ→マーケットプレースで,
「websphere ?liberty」を検索索
–?IBM ?WebSphere ?Application ?Server ?Liberty ?Pro?le
Developer ?Tools ?for ?Luna ?Beta ?を選んで導?入
§??サーバー作成画?面から,
Libertyプロファイルを
直接ダウンロードして
導?入できます
45
JJUG ?Cross ?Community ?Conference ?2014 ?Fall
まとめ
§??WebSocketは,より?高機能なHTML5アプリケーションを
作成するためのキーテクノロジーです
§??現在ではWebSocketを使?用するための環境は,
ほぼととのってきたといえます
§??WebSphere ?Application ?Server
Libertyプロファイルを使?用すれば
WebSocketを今すぐ試すことができます
46

More Related Content

いよいよ始められる Java EEて?のWebSocket #jjug #jjug_ccc #ccc_r21

  • 1. ? 2013 IBM Corporation JJUG ?Cross ?Community ?Conference ?2014 ?Fall いよいよ始められる Java ?EEでのWebSocket 1
  • 2. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Agenda §??Java ?EE ?7とHTML5 §??WebSocketとは §??WebSocketの現状 §??Java ?EEでのWebSocketアプリ開発 2
  • 3. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Java ?EE ?7とHTML5 3
  • 4. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Java EE 7の三つのゴール §??HTML5環境への対応 §??開発?生産性の向上 §??エンタープライズ?ニーズへの対応 4
  • 5. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 三つのゴールとJava ?EE仕様群との対応 §??HTML5環境への対応 –? JSR 344: JavaServer Faces (JSF) 2.2 –? JSR 353: Java API for JSON Processing (JSONP) 1.0 –? JSR 356: Java API for WebSocket 1.0 –? JSR 339: Java API for RESTful Web Services (JAX-RS) 2.0 §??開発?生産性の向上 –? JSR 345: Enterprise JavaBeans (EJB) 3.2 –? JSR 346: Contexts and Dependency Injection for Java EE (CDI) 1.1 –? JSR 907: Java Transaction API (JTA) 1.2 –? JSR 349: Bean Validation 1.1 §??エンタープライズ?ニーズへの対応 –? JSR 343: Java Message Service (JMS) 2.0 –? JSR 338: Java Persistence API (JPA) 2.1 –? JSR 236: Concurrency Utilities for Java EE 1.0 –? JSR 352: Batch Applications for the Java Platform 1.0 5
  • 6. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 2014年年10?月 ?ついに正式勧告となったHTML5 §??従来のHTML –?画面をレンダリングするための規格 §??HTML5(+ ?CSS3 / JavaScript) –?アプリケーションを記述するための規格 6
  • 7. JJUG ?Cross ?Community ?Conference ?2014 ?Fall HTML5環境の新しいアプリケーションスタイル §??「サーバーサイドMVC」から「クライアントMVC」へ 7 Web Browser Application Server Application HTTP Request HTML/JS Controller Session Data View Business LogicModel DomainDomain Web Browser Application Server Application View HTML/JS Controller Data Store Model Model DomainDomain RESTful or WebSocket JSON Business Logic 従来のWebアプリケーション Single Page Application (SPA)
  • 8. JJUG ?Cross ?Community ?Conference ?2014 ?Fall HTML5におけるクライアント?サーバー連携 §??通信?方法 –?RESTful (JAX-RS 2.0) ?? HTTPの原則にしたがった 簡潔なシステム間連携の設計手法 –?WebSocket (WebSocket 1.0) ?? ブラウザとWebサーバーの間で 双方向通信を可能にする 通信プロトコル §??データ型 –?JSON:JavaScript Object Notation (JSONP 1.0) ?? JavaScriptのオブジェクトとして そのままパースできる テキスト形式のデータ表記法 8 Web Browser Application Server Application View HTML/JS Controller Data Store Model Model DomainDomain RESTful or Web Socket JSON Business Logic
  • 9. JJUG ?Cross ?Community ?Conference ?2014 ?Fall HTTP通信によるサーバー連携の問題点 §??基本的に半?二重通信 –?ひとつのHTTPのセッションで 「?一回のリクエスト」と「?一回のレスポンス」 –?Keep ?Aliveにより複数のセッションを ?一つのTCPコネクションで繰り返すことは可能 §??サーバーのイベントをトリガーとした通信が困難 –?リクエストの送信はクライアントからだけ §??通信が冗??長 –?リクエスト?レスポンス毎に多くのヘッダ情報 9
  • 10. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 従来のブラウザとの双?方向通信 §??従来のWeb技術で双?方向通信を実現するには Comet技術などで無理理?矢理理,実現していた –?サーバーはリクエストの応答を返さずにイベントが発生するまで待機 10
  • 11. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 新しい双?方向通信:WebSocket §??WebSocketを使?用すると双?方向通信を?自然な形で実現 –?HTTPで通信を開始して, Protocol SwitchingによりWebSocketに移行 –?サーバー側からもクライアント側からもメッセージを送信可能 11
  • 12. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocket ?URI §??URIスキームとして以下を使?用する –?ws:// ? ? ? ?WebSocketによるNon-‐??SSL通信(80ポート) –?wss:// ? ? ? ?WebSocketによるSSL通信(443ポート) §??httpと同様に80/443ポートを使?用するため 多くの環境でFirewallの追加設定は不不要 12
  • 13. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocketのハンドシェイク §??HTTPでWebSocketのハンドシェイクを?行行う 13 HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat (オプション) Sec-WebSocket-Version: 13 HTTP GETリクエストでOpening Handshakeを送信 ステータスコード101を返してWebSocketにプロトコルスイッチ
  • 14. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocketのライフサイクル 14 WebSocketの接続状態 CONNECTING OPEN CLOSING CLOSED Opening Handshake Closing Handshake データの送受信 ? ? ? TCP接続の切断 クライアント サーバー TCP接続の確立
  • 15. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocketの?用語 §??WebSocketエンドポイント ?(endpoint) §?? WebSocketの確?立立された接続の両端をうけもつ2つのコンポーネント §??クライアントエンドポイントとサーバーエンドポイント (client ?endpoint ?and ?server ?endpoint) §?? 接続を開始した側のエンドポイントと, 接続を待ち受けていた側のエンドポイント §??ピア ?(peer) §?? 接続している相?手側のエンドポイント §??WebSocketセッション ?(session) §?? ?二つのエンドポイントの間で確?立立されている通信セッション 15
  • 16. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 既存技術との?比較 §??Ajax –?定期的にポーリング –?最?大でポーリング間隔の タイムラグが発?生する –?あまりポーリング間隔を 短くするとサーバーに負荷が 16 §??Comet –?イベントが発?生するまで 応答を遅延させる –?クライアントからの イベント通知には不不向き HTML JS クライアント サーバー CSS Data#2 Data#1画面遷移 Dataなし Data#3 HTML JS クライアント サーバー CSSData#1画面遷移 イベン ト発生 待機 イベン ト発生 待機 Data#2 Data#3
  • 17. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocketのメリット §??双?方向リアルタイム通信における技術的な課題を解決 17 比較項目 Ajax Comet WebSocket 使用プロトコル HTTP HTTP WebSocket(ハンドシェイ ク時にHTTPを利用) 1回のTCP接続で可能 なデータ取得回数(*) 1回 (要求/応答の1往復) 1回 (要求/応答の1往復) 複数回 クライアントからの Pull型データ取得 可能 可能 可能 サーバーからの Push型データ配信 不可能 ロングポーリングによる 擬似的Push配信 可能 リアルタイム通信 不向き (ポーリングが必要) ロングポーリングによる 擬似的リアルタイム通信 可能 HTTPヘッダーの オーバーヘッド あり あり なし TCPハンドシェイクに よるオーバーヘッド あり(*) あり(*) なし (*)HTTP KeepAliveを使用しない場合
  • 18. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocketの現状 18
  • 19. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocket プロトコルの現状 §??プロトコルはIETF / RFCで標準化 –?2010年年2?月? draft-hixie-thewebsocketprotocol-75 –?2010年年5?月? draft-ietf-hybi-thewebsocketprotocol-00 –?2011年年4?月? draft-ietf-hybi-thewebsocketprotocol-07 –?2011年年7?月? draft-ietf-hybi-thewebsocketprotocol-10 –?2011年年12?月? RFC 6455 "The WebSocket Protocol" §??W3CでJavaScript APIを仕様化 –?2009年年4?月? First Public Draft –?2009年年10?月?~2012年年8?月? Working Draft –?2012年年9?月 W3C Candidate Recommendation 19
  • 20. JJUG ?Cross ?Community ?Conference ?2014 ?Fall ブラウザの対応状況 20 §??モダンなブラウザの?大部分がサポート MSIE 10 (2013/2) ?~ Chrome 16 (2011/12) ?~ Firefox 11 (2012/3) ?~ Safari 6 (2012/7) ?~ iOS 6.0 (2012/9) ?~ Android 4.4 (2013/10) ?~
  • 21. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 対応ブラウザのシェア 21 §??70%以上のブラウザがWebSocketに対応 出典:NetMarketShare.com Market Share Reports October, 2014
  • 22. JJUG ?Cross ?Community ?Conference ?2014 ?Fall 商?用Java ?EEサーバーでもサポートが開始 §??2014年年7?月? Oracle ?WebLogic ?Server ?12.1.3で対応 §??2014年年12?月 ?IBM ?WebSphere ?Application ?Server ?8.5.5 ?  ?  ?Libertyプロファイルで対応 22
  • 23. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Webサーバー?プラグインの対応 §??IBM ?HTTP ?Server(IHS) –?2014年年8?月 ?IHS ?/ ?WAS ?Plug-‐??in ?8.5.5.3で対応 §??Load ?Balancer –?WAS ?NDに同梱のLoad ?BalancerもWebSocketのふりわけが可能 –?F5 ?BIG-‐??IPなどもアプライアンス製品もWebSocketに対応 ? ? コネクション数の上限には注意 23 WAS WAS IHS Plug-in IHS Plug-in ?  Load Balancer
  • 24. JJUG ?Cross ?Community ?Conference ?2014 ?Fall クライアント側にProxyがある場合 §??WebSocketのリクエストはCONNECTメソッドで開始 §??TLS ?/ ?SSLが正常につかえる環境であればOK §??すでにAjax ?/ ?Cometが多数普及しているため ??長時間のコネクションへの対応は済んでいる(はず) 24 _Proxy Usage_: If the client is configured to use a proxy when using the WebSocket Protocol to connect to host /host/ and port /port/, then the client SHOULD connect to that proxy and ask it to open a TCP connection to the host given by /host/ and the port given by /port/. EXAMPLE: For example, if the client uses an HTTP proxy for all traffic, then if it was to try to connect to port 80 on server example.com, it might send the following lines to the proxy server: CONNECT example.com:80 HTTP/1.1 Host: example.com RFC 6455
  • 25. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Java ?EEでの WebSocketアプリ開発 ? 25
  • 26. JJUG ?Cross ?Community ?Conference ?2014 ?Fall JSR ?356: ?Java ?API ?for ?WebSocket ?1.0 ? §??JavaでWebSocket通信を実装するためのAPI §??クライアントとサーバーの両?方をサポート §??Java ?SE環境での実?行行も考慮された仕様 §??アノテーションをベースとした モダンなプログラミングスタイル §??Encoder ?/ ?Decoderにより 扱うデータ型を柔軟に制御 26
  • 27. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Endpoint:ServerEndpointとClientEndpoint §??WebSocket通信の両端となるEndpointの作成が必須 –?WebSocket通信の開始?終了了?エラー発?生と メッセージ受信をトリガーにEndpointのメソッドが呼び出される §??クライアントはブラウザで実装することが多いので, 多くの場合Java ?EEではサーバー側のEndpointを実装する 27 ClientEndpoint ServerEndpoint Session @OnMessage public void message(... ) @OnOpen public void open(... ) @OnClose public void close(... ) @OnMessage public void message(... ) @OnError public void error(... )
  • 28. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Endpointの作成 §???二つの実装?方法 –?アノテーションをつけたPOJO ??@javax.websocket.server.ServerEndpoint ??@javax.websocket.ClientEndpoint –?javax.websocket.Endpointを継承したクラス アノテーションベースのPOJOで実装するほうが簡単 28
  • 29. JJUG ?Cross ?Community ?Conference ?2014 ?Fall アノテーションによるEndpoint実装の例例 29 @ServerEndpoint("/echo")? public class EchoServiceEndpoint{ Session currentSession = null; //接続がオープンしたとき? @OnOpen? public void onOpen(Session session, EndpointConfig ec) {? currentSession = session;? } //メッセージを受信したとき? @OnMessage? public void receiveMessage(String msg) throws IOException {? //メッセージをクライアントに送信する? currentSession.getBasicRemote().sendText("Hello" + msg);? } //接続がクローズしたとき? @OnClose? public void onClose(Session session, CloseReason reason) { ??? ?} //接続エラーが発?生したとき? @OnError? public void onError(Throwable t) {??? ?} }
  • 30. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocket ?1.0で定義されているアノテーション §?? @ServerEndpoint ?/ ?@ClientEndpoint –?サーバー側 ?/ ?クライアント側のエンドポイント §?? @OnOpen ?/ ?@OnMessage ?/ ?@OnError ?/ ?@OnClose –?ライフサイクルのイベントで呼び出されるメソッド §?? @PathPram –? リクエストURIのパスの?一部をパラメーターとして受け取る 30 アノテーション イベント 例 @OnOpen 接続がオープンしたとき @OnOpen Public void open(Session session, EndpointConfig conf) {} @OnMessage メッセージを受信したとき @OnMessage Public void message(Session session, String msg) {} @OnError 接続エラーが発生したとき @OnError public void error(Session session, Throwable error) {} @OnClose 接続がクローズしたとき @OnClose Public void close(Session session, CloseReason reason) {} @ServerEndpoint(value = “/sample/{name}”) Public class SampleEndpoint { @OnOpen public void open(Session session,EndpointConfig ec, @PathParam("name") String name) { ??? }
  • 31. JJUG ?Cross ?Community ?Conference ?2014 ?Fall JVMJVM Endpointのインスタンス §??Endpointのインスタンスは WebSocketのセッションごとに別個に作成される –?Servletのインスタンスが,サーバーに?一つ作成されて 複数のリクエスト?セッションで共有されるのと対照的 31 Endpoint インスタンス Servlet インスタンス
  • 32. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Endpointのコーディング(1) §??セッションの情報をインスタンス変数に保存できる –?多くの場合,javax.websocket.Sessionの保存は必須 §??「時間のかかる初期化処理理」はEndpoint毎には書かない –?@Singletonの@EJBなどに実装しておいて呼び出す 32 @ServerEndpoint(value = "/echo") public class EchoServiceEndpoing { private Session currentSession; @OnOpen public void onOpen(Session session, EndpointConfig ec) { currentSession = session;
  • 33. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Endpointのコーディング(2) §??マルチスレッドを考える必要はない –?それぞれのインスタンスの@OnOpenメソッドなどが 複数スレッドから同時に呼ばれることはない –?ただし複数のEndpoint ?/ ?Sessionにまたがる処理理では, 状況に応じて排他制御が必要 33
  • 34. JJUG ?Cross ?Community ?Conference ?2014 ?Fall ピアへのメッセージの送信 §??SessionからRemoteEndpointを取得して使?用する §??RemoteEndpointは,2種類 –?RemoteEndpoint.Async ?非同期通信 –?RemoteEndpoint.Basic 同期通信 §??Sessionは 他のスレッドで稼働しているServlet ?/ ?EJBからも利利?用可能 –?複数スレッドから?一つのSessionを同時に利利?用することは避ける 34 if (session.isOpen())? session.getBasicRemote().sendText(msg);
  • 35. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Encoder ?/ ?Decoder §??ピアとの間で送受信するのは?文字列列かバイナリ §??変換をおこなうEncoder ?/ ?Decoderをおくことで エンドポイントからJavaのオブジェクトで 送受信することができる 35 ServerEndpoint @OnMessage public void message(... ) @OnOpen public void open(... ) @OnClose public void close(... ) Decoder Encoder String / byte列列 Javaの オブジェクト
  • 36. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Decoder ?/ ?Encoder ?の実装と利利?用 §??インターフェースをimplementsする §??@ServerEndpoint ?/ ?@ClientEndpoint ?に追記 36 class MyObjectDecoder implements Decoder.Binary<MyObject> { @Override public boolean willDecode(ByteBuffer buf) { ... } @Override public MyObject decode(ByteBuffer arg0) throws DecodeException { ... } @ServerEndpoint(value = "/chat", decoders = MyObjectDecoder.class) public class ChatService {
  • 37. JJUG ?Cross ?Community ?Conference ?2014 ?Fall HTTPヘッダ?HttpSessionへのアクセス §??Con?guratorのmodifyHandshakeメソッドを利利?用する –?HandshakeRequestからHTTPヘッダやHttpSessionが取得できる ? §??@ServerEndpoint ?/ ?@ClientEndpoint ?に追記 37 import javax.websocket.server.ServerEndpointConfig.Configurator; public class ChatConfig extends Configurator { @Override public void modifyHandshake(ServerEndpointConfig sec,? HandshakeRequest req,? HandshakeResponse resp) { @ServerEndpoint(value = "/chat", configurator = ChatConfig.class) public class ChatService {
  • 38. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Con?guratorからEndpointへの情報伝達 §??EndpointCon?gのUserPropertiesを利利?用する 38 public void modifyHandshake(ServerEndpointConfig config,? HandshakeRequest req, HandshakeResponse resp) {? ? HttpSession session = (HttpSession)request.getHttpSession();? Map<String,Object> userProps = config.getUserProperties();? userProps.put("MyID", ? (session != null)? session.getAttribute("MyID") : "No ID"); @OnOpen public void onOpen(Session session, EndpointConfig config) { ? Map<String,Object> userProps = config.getUserProperties(); String myID = (String)userProps.get("MyID"); Configurator Endpoint
  • 39. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Con?guratorやEndpointでHttpSessionを書き換えない §??HandshakeRequestからHttpSessionは取得できるが, Attributeのセット?更更新?削除は危険 –?分散環境では,HttpSessionの内容は複数サーバー間で共有される –?多くのアプリケーションサーバーでは,サーバー間の HttpSession情報の更更新はリクエスト処理理が完了了した時に実?行行 –?WebSocketでは,セッションが短時間で終了了しない → ?変更更内容が他のサーバーになかなか伝搬しない §??Con?guratorでは, HttpSessionから読み取りのみをおこなうのが安全 39
  • 40. JJUG ?Cross ?Community ?Conference ?2014 ?Fall さらに詳細に知りたい場合は §??IBM ?developerWorksでWebSocketを検索索 40 Java EE 7 アプリケーション設計ガイド ?– WebSocket編 http://www.ibm.com/developerworks/jp/websphere/library/was/javaee7_appguide/1.html
  • 41. JJUG ?Cross ?Community ?Conference ?2014 ?Fall いますぐ WebSocketを試すには 41
  • 42. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WASの新しいランタイム:Libertyプロファイル 42 WAS V8.5.5 Liberty & WDT Web Profile準拠 Java EE 6のWeb Profile標準に 準拠したアプリを完全サポート JAX-WS, JAX-RS, JMSもサポート Unzipによる導?入とデプロイ パッケージをした サーバー ?+ アプリ ?+ 構成情報を Unzipでデプロイ可能 簡単な構成と動的変更更 最低限必要な構成ファイルは server.xmlひとつだけ デフォルトベースで簡単構成 構成変更更は再起動なしに反映 軽量量ランタイム メモリー使?用量量が?小さい: 60MB程度度?~ ディスク使?用量量も100MB以下 起動が速い 起動時間: 5秒程度度 統合ツール(WDT) ?高機能なEclipse?用の連携ツールを無償で提供 Eclipseから簡単に使?用可能 ?自動化ツールとの連携 多くのOSSツールに 無償でプラグインを提供
  • 43. JJUG ?Cross ?Community ?Conference ?2014 ?Fall API?サーバー機能をFeatureとして定義 §??必要なものだけを構成 ? –?設定されたものだけがメモリにロード?初期化される → ?最?小限の起動時間?メモリー使?用 43 ServletJSPJDBCSSL JAX-RS sessionDatabase <featureManager> ? ? ? ? ?<feature>jsp-?‐2.2</feature> ? ? ? ? ?<feature>jdbc-?‐4.0</feature> ? ? ? ? ?<feature>jaxrs-?‐1.1</feature> ? ? ? ? ?<feature>sessionDatabase-?‐1.0</feature> ? ? ? ? ?<feature>ssl-?‐1.0</feature> ? </featureManager> ? 構成ファイル ?server.xml 依存関係も ?自動的に解決 JSON
  • 44. JJUG ?Cross ?Community ?Conference ?2014 ?Fall WebSocketにも対応したBeta版を無償公開中 §??現在,Java ?EE ?7の?一部の機能を実装した LibertyプロファイルをBetaとして公開 §??websocket-‐??1.0フィーチャーを有効にすれば WebSocketアプリケーションを実?行行可能 44 <featureManager> ? ? ? ? ?<feature>jsp-?‐2.2</feature> ? ? ? ? ?<feature>jdbc-?‐4.0</feature> ? ? ? ? ?<feature>websocket-?‐1.0</feature> ? </featureManager> ?
  • 45. JJUG ?Cross ?Community ?Conference ?2014 ?Fall Eclipseにマーケットプレースから開発者ツールを導?入 §??メニューからヘルプ→マーケットプレースで, 「websphere ?liberty」を検索索 –?IBM ?WebSphere ?Application ?Server ?Liberty ?Pro?le Developer ?Tools ?for ?Luna ?Beta ?を選んで導?入 §??サーバー作成画?面から, Libertyプロファイルを 直接ダウンロードして 導?入できます 45
  • 46. JJUG ?Cross ?Community ?Conference ?2014 ?Fall まとめ §??WebSocketは,より?高機能なHTML5アプリケーションを 作成するためのキーテクノロジーです §??現在ではWebSocketを使?用するための環境は, ほぼととのってきたといえます §??WebSphere ?Application ?Server Libertyプロファイルを使?用すれば WebSocketを今すぐ試すことができます 46