Hatena::ブログ(Diary)

tomoTakaの日記

2015-12-31

SDKMANを使ってSpringBootのインストールを試してみました

久しぶりにSpringBootを復習してみようとドキュメントを読んでいるとSDKMANを使ったインストール方法と、WebApplicationをGroovyを使ったサンプルがSpring Boot Reference Guideここで紹介されていたので試してみました。

インストール

sdk install springboot

f:id:tomoTaka:20151231112827p:image:w360

groovyでweb applicationを実装

上記のドキュメントを実装

@RestController
class ThisWillActuallyRun {
    @RequestMapping("/")
    String home() {
        "Hello World!"
    }
}
  • 起動コマンド
spring run app.groovy

f:id:tomoTaka:20151231113352p:image:w200

Javaでも動作するかを試してみました

上記のドキュメントを実装

import org.springframework.boot.*;
import org.springframewowk.boot.autoconfigure.*;
import org.springframework.boot.stereotype.*;
import org.springframework.web.bind.annotatin.*;

@RestController
@EnableAutoConfiguration
public class Example {
    @RequestMapping("/")
    String home() {
        return "Hello World!(Java) ";
    }

    public static void main(String... args) throws Exception {
        SpringApplication.run(Example.class , args);
    }
}
  • 起動コマンド
spring run Example.java

f:id:tomoTaka:20151231112246p:image:w200
Javaでもコンパイルしないで動作しました。すごく便利です!

2015-12-20

ちょっと試してみた

ここGet started with Dockerを参考に再度インストール

インストール

インストールできた。っと思ったらエラーが発生して動作しない。そもそも以前にboot2dockerインストールしたままだった(汗)
f:id:tomoTaka:20151219152137p:image:w380

ここDocker uninstallを参考にいろいろ削除などして、再度インストール、なんとかDocker run コマンドは動作するようになりましたが、、、

  • boot2dockerを削除
boot2docker stop
boot2docker delete
  • 不要なファイルを削除

/usr/local/bin 配下のファイルなどを削除

.bash_profile のDOCKERに関する指定を削除

次に以下のコマンドでのDocker Hub へのログインで認証エラー?

docker login --username=xxx --emial=xxxx

ぐぐった結果以下のコマンドを実行。ユーザー、パスワード、emailがきかれるのでそれぞれ入力して無事loginできました。

docker login

Docker Hub

なんとか作成したRepositoryにpushできました。
f:id:tomoTaka:20151220090318p:image:w550

まだまだ勉強しないと、、、

2015-12-13

JDK9で起動しなくなった時の対処

JDK9をダウンロードインストールNetBeansが起動しなくなった、、、
で調べてみると、なんだか「Perm Gen options」が問題なようです。[JDK-8038827] Perm Gen options partially removed and partially only ignored - Java Bug System
NetBeansのここUsing NetBeans IDE on Mac OS Xをみてjdkhomeが指定できるようなので
以下のようにjdk8で起動するようにしたら起動できました。

  • ApplicationのNetBeans.appで「control」+クリックで、「パッケージの内容を表示」をクリック

f:id:tomoTaka:20151213073526p:image:w350

  • 以下のフォルダの「netbeans.conf」ファイルを開く

f:id:tomoTaka:20151213073542p:image:w350

「netbeans_jdkhome」の行でJDK8を指定
f:id:tomoTaka:20151213073614p:image:w550
いろいろ知らないことがあったのですが、とても勉強になりました。

Server Event Client Sample

no titleの13日目です。
昨日は@さんのJavaFX と Project Jigsaw - JavaFX in the Boxでした。
明日は@さんです。
前回Server Sent Event のサーバー処理についてちょっと実装を試したJava EEエヴァンジェリストによる!EE 8最新動向!に行ってきました! - tomoTakaの日記のですが、クライアントJavaで実装できると紹介されていたので、JavaFXサーバーから受信したレスポンスをアニメーションで表現してみるのに挑戦しました。
ですが、そもそもアニメーションがよくわかっていなくて、、、
2パターンの実装は、ここno titleを参考にしました。

画面

リクエスト送信ボタンをクリックした後、指定したタスク数の「Task0〜5の結果」ラベルが左(サーバー)から右(クライアント)へタスク処理時間で指定した時間の間隔で移動します。
「リクエスト送信(非同期)」ボタンの処理は思ってようにアニメーションしますが、「リスエスト送信(同期)」ボタンの処理は、アニメーションで複数のラベルが同時になってしまいます???

  • 初期表示時

f:id:tomoTaka:20151212153445p:image:w350

  • リスエスト送信(非同期)ボタンクリック後

f:id:tomoTaka:20151212153517p:image:w370

実装

  • 非同期処理

アニメーションの部分はコメントいただいて修正しています。

    @FXML
    private void requestAction2(ActionEvent event){
        listeningProperty.setValue(Boolean.TRUE);
        disableProperty.setValue(Boolean.FALSE);
        int taskCntVal = taskCnt.getValue();
        int taskIntervalVal = taskInterval.getValue();
        String url = "http://localhost:8080/event/" 
                + taskCntVal + "/" + taskIntervalVal;
        Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
        WebTarget target = client.target(url);
        eventSource = EventSource.target(target).build();
        eventSource.register(inboundEvent ->{
            String data = inboundEvent.readData(String.class);
            int id = Integer.parseInt(inboundEvent.getId());
            Label label = labels[id];
            TranslateTransition t = transitions[id]; // **サーバーより受信したIDで実行するアニメーションを設定
            Platform.runLater(()->{
                label.setText(data); // **ラベルにサーバーより受信した結果を設定
                new Timeline(new KeyFrame(Duration.millis(500), e-> t.play())).play(); / **アニメーション開始
            });
        }, "message-client");
        eventSource.open();
    }

修正後

            Platform.runLater(()->{
                 label.setText(data);
                TranslateTransition t = new TranslateTransition(Duration.millis(300), label);
                t.setFromX(0);
                t.setToX(-200);
                t.play();  // **アニメーション開始
            });
  • 同期処理
    @FXML
    private void requestAction1(ActionEvent event) {
        listeningProperty.setValue(Boolean.TRUE);
        disableProperty.setValue(Boolean.FALSE);
        Arrays.stream(labels).forEach(l -> l.setText(null));
        int taskCntVal = taskCnt.getValue();
        int taskIntervalVal = taskInterval.getValue();
        String url = "http://localhost:8080/event/" 
                + taskCntVal + "/" + taskIntervalVal;
        Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
        WebTarget target = client.target(url);
        EventInput eventInput = target.request().get(EventInput.class);
        while (!eventInput.isClosed()){
            InboundEvent inboundEvent = eventInput.read();
            if (inboundEvent == null){
                break;
            }
            int id = Integer.parseInt(inboundEvent.getId());
            Label label = labels[id];
            String data = inboundEvent.readData(String.class);
            label.setText(data);                
            TranslateTransition t = transitions[id];
            new Timeline(new KeyFrame(Duration.millis(500), e-> t.play())).play();
        }
    }
  • 初期処理

アニメーションの初期設定など

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        labels = new Label[] {label1, label2, label3, label4, label5};
        Arrays.stream(labels).forEach(l -> l.setText(null));
        transitions = new TranslateTransition[]{
            new TranslateTransition(Duration.millis(500), label1)
           ,new TranslateTransition(Duration.millis(500), label2)
           ,new TranslateTransition(Duration.millis(500), label3)
           ,new TranslateTransition(Duration.millis(500), label4)
           ,new TranslateTransition(Duration.millis(500), label5)
        };
        Arrays.stream(transitions).forEach(t -> {
            t.setFromX(0);
            t.setToX(-200);
        });
        // Buttonの使用制御
        listeningProperty = new SimpleBooleanProperty(false);
        startBtn1.disableProperty().bind(listeningProperty);
        startBtn2.disableProperty().bind(listeningProperty);
        disableProperty = new SimpleBooleanProperty(true);        
        closeBtn.disableProperty().bind(disableProperty);
    }    

実装はここno titleにアップしています。
JavaFXの問題ではないのですが、非同期処理を実行するとサーバーへ何度もリクエスト送信されてしまいます?(汗)
すごく中途半端な状態で申し訳ないですが、アドバイスいただければ幸いです、、、
アニメーション難しいです、まだまだ勉強不足です、、、

2015-12-05

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

no titleに行ってきました。

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など盛りだくさんでした。
no title
最後に質問タイムがあって、質問者にはJavaOneのTシャツがプレゼントされました。

でServer Sent Event はJerseyですでに実装されているとお聞きしたので早速試してみました。
no titleno titleを参考にサーバ側を実装。
HTML5 Server-Sent Eventsを参考にクライアント側を実装。

Server Sent Event を試してみました

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

f:id:tomoTaka:20151205161044p:image:w300

なぜかエラーイベントが発生?
f:id:tomoTaka:20151205161148p:image:w380

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>

サーバ側はここno titleにアップ
クライアントHTMLはここno titleにアップ
参加者全員にJava20年のステッカーいただきました!
f:id:tomoTaka:20151205181530p:image:medium
スタッフの方々、参加者の皆さんお疲れさまでした。とても楽しく有意義な時間を過ごせました!!!

2015-11-22

Rakuten Technology Conference2015

This is the third time for me to participate in Rakuten Technology Conference.
When I registered they gave me a pretty charm and a introduction card.
f:id:tomoTaka:20151122064409j:image:w250:leftf:id:tomoTaka:20151122064340j:image:w250

I was so nervous and made a mistake on my card. The word greate should be great. :-(
You can get the Time Table and some information about the conference here.Osaka Satellite: Rakuten Technology Conference 2015 on Nov. 21st - Mitsuyuki.Shiiba
I felt that all speakers have passions for their idea. And I was impressed by them.
Also I talked with a lot of nice people.
The staff allowed me to introduce the workshop which is hold next weekend about JavaEE8 in English.
no title
It is very difficult for me to write the blog in English.
I would like to thank all of staff!!!

Connection: close