Java EEエヴァンジェリストによる!EE 8最新動向!に行ってきました!

Java EEエヴァンジェリストによる!EE 8最新動向! - connpassに行ってきました。

JavaOne 2015 サンフランシスコ サマリー

@さんによるJavaOneのお話。
現場での裏話(ケーキのお話とか、蟹パーティー)もあったりして楽しかったです。
それとJavaチャンピオン、JCP、などJavaに関するお話もあって初めて勉強会に参加した方がJavaに関心を持ってくれたのも嬉しかったです!
(実際1週間前に別のイベントOsaka Satellite: Rakuten Technology Conference 2015 on Nov. 21st - Mitsuyuki.Shiibaでお会いした学生さん@ ]が参加してJavaEEに興味を持っていただいて良かったです)

Java EE 8 最新動向

@さんによるJavaEE8のお話。
JavaEE8で追加される機能の紹介で、JSON, HTTP2, Server Sent Eventなど盛りだくさんでした。
David Delabassee’s Presentations on SlideShare
最後に質問タイムがあって、質問者にはJavaOneのTシャツがプレゼントされました。

でServer Sent Event はJerseyですでに実装されているとお聞きしたので早速試してみました。
Chapter 15. Server-Sent Events (SSE) Supportjersey/examples/server-sent-events at master · jersey/jersey · GitHubを参考にサーバ側を実装。
HTML5 Server-Sent Eventsを参考にクライアント側を実装。

Server Sent Event を試してみました

  • 画面1(URLを指定しただけ)

なぜかエラーイベントが発生?

  • サーバ側

EventOutput、OutboundEventなど初めて知りました。勉強しないといけないことが沢山です。(汗)

package com.mycompany.sseserversample;

import java.io.IOException;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.media.sse.EventOutput;
import org.glassfish.jersey.media.sse.OutboundEvent;
import org.glassfish.jersey.media.sse.SseFeature;
import org.glassfish.jersey.server.ResourceConfig;

/**
 * Sever Sent Event Sample.
 * 
 * @author tomo
 */
@Path("event/{task-cnt}/{task-interval}")
public class ServerSample {
    public static void main(String... args) throws IOException, InterruptedException{
        ResourceConfig config = new ResourceConfig(ServerSample.class, SseFeature.class);
        URI uri = URI.create("http://localhost:8080/");
        HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri, config, false);
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            server.shutdownNow();
        }));
        server.start();
        System.out.println("Server started. Stop the Application using CTR-C");
        Thread.currentThread().join();
        System.out.println("Server end.");
    }
    
    @GET
    @Produces(SseFeature.SERVER_SENT_EVENTS)
    public EventOutput getServerSentEvents(@PathParam("task-cnt") int taskCnt,
            @PathParam("task-interval") int taskInterval){
        System.out.println("*taskcnt=" + taskCnt +", " + taskInterval);
        final EventOutput eventOutput = new EventOutput();
        new Thread(() -> {
            try {
                for (int i = 0; i < taskCnt; i++) {
                    TimeUnit.SECONDS.sleep(taskInterval);
                    final OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
                    eventBuilder.name("message-client");
                    eventBuilder.data(String.class, "Hello world " + i);
                    eventBuilder.comment("comment"+ i);
                    eventBuilder.id("id"+ i);
                    final OutboundEvent event = eventBuilder.build();
                    eventOutput.write(event);
                }
            } catch (IOException | InterruptedException ex) {
                Logger.getLogger(ServerSample.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    eventOutput.close();
                } catch (IOException ex) {
                    Logger.getLogger(ServerSample.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }).start();
        return eventOutput;
    }
}
  • クライアント側

EventSource初めて知りました。本当に次々新しい機能があって楽しいです!

<!DOCTYPE html>
<html>
    <head>
        <title>Server Sent Event Sample</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <h2>Server Sent Event Sample</h2>
        <div>
            <label>Task count:</label>
            <input type="number" id="task_count" />
            <label>Task interval:</label>
            <input type="number" id="task_interval" />
        </div>
        <div>
            <button id="sendBtn">Server Send Event Start</button>
            <button id="closeBtn">Server Send Event Close</button>
        </div>
        <div>
            <h3>Received Messages</h3>
            <output id="result"></output>
        </div>
        <script>
            'usestrict';
            (function(){
                var sendBtn = document.getElementById('sendBtn');
                var closeBtn = document.getElementById('closeBtn');
                var result = document.getElementById('result');
                var eventSource = null;
                // close button click event 
                closeBtn.addEventListener('click', function(){
                    if (eventSource){
                        eventSource.close();
                    }
                });
                // start button click event 
                sendBtn.addEventListener('click', function(){
                    if (typeof (EventSource) !== void 0){
                        //EventSource がサポートされている場合
                        result.insertAdjacentHTML('beforeend', 
                            '<li>EventSource supported!</li>');
                        var taskCnt = document.getElementById('task_count').value;
                        var taskInterval = document.getElementById('task_interval').value;
                        var url = 'http://localhost:8080/event/' 
                                + taskCnt + '/' + taskInterval + '/';
                        eventSource = new EventSource(url);
                        eventSource.addEventListener('message-client', function(event){
                        result.insertAdjacentHTML('beforeend', 
                            '<li>' + event.data + '</li>');
                        });
                        eventSource.onerror = function(){
                            result.insertAdjacentHTML('beforeend', 
                            '<li>EventSource Error!</li>');
                            eventSource.close();
                        };
                    } else {
                        //EventSource がサポートされていない場合
                        result.insertAdjacentHTML('beforeend', 
                            '<li>not support EventSource</li>');
                    }
                });
            }());
        </script>
    </body>
</html>

サーバ側はここGitHub - tomoTaka01/SseServerSample: Server Send Event Server Sampleにアップ
クライアントのHTMLはここHTML file for Server Sent Event JavaScript Sample · GitHubにアップ
参加者全員にJava20年のステッカーいただきました!

スタッフの方々、参加者の皆さんお疲れさまでした。とても楽しく有意義な時間を過ごせました!!!