2014/08/24

関西WildFly 8(旧JBoss AS)勉強会に参加したときのメモ

2014-08-23 に 関西WildFly 8(旧JBoss AS)勉強会 に参加したときのメモ。

* What's new in WildFly 8 - @nekop (slide @arunguputa)
** Arun Guputa -> OracleからRedhatに移った模様
** WildFlyはJBossAS7の後継
   ググラビリティが悪いので(JBoss.orgの他のプロダクトと被るので)改称
** Undertow
   内部的にはTomtcat使ってたけど、Tomcatのバージョンアップはさほど後方互換を重視していなかったので
   メンテが大変だった。
   エンタープライズ用途に厳しいということでUndertowをフォークして作成。
   今はそれを使っている。
** 使用ポートを整理   
   アプリ用のポートは2本まで減らした。
    - app: 8080
    - mng: 9990
   ※デフォルト値
** What's new(Java EE7)
*** WebSocet(JSR356) New
*** Batch(JSR 352) New
    XMLで定義....だと?(仕様はIBMが策定)
    ※でかいバッチを本気で作ったらどんなXMLになっちゃうんだろう?と会場では話題に
*** JSON(JSR 353) New
*** Concurrency(JSR 236) New
    いままではThread扱えない
    Java EE自体が ThreadLocalをごりごり使う。
    ユーザ記述ロジックで立ち上げたThreadにはそういうのがなくて管理できずに爆発する。

    というのをどうにかして、管理可能な状態でThreadを作成する口が作られた。
    Fork/Joinもできる
*** JAX-RS(JSR 339) update
    RESTClientが誕生
    Jerseyベース(not RESTEasy)
*** JMS (JSR 343) update
    呼び出しが簡素化(7行くらい -> 1行)
*** JTA(JSR 907) update
    EJBによる管理だけではなく、CDI側で管理できるようになる
*** CDI (JSR 346) update
    beans.xmlがoptional
    スキャンタイプを選べるようになる(前は全てのクラスをスキャンしていた)
    All scanは遅いことがある(今まではAll Scan)

    - All scanはくっそ遅い、となることがある
    - 自前のクラスとJar内部クラスがバッティングして
      Injection対象がわからないエラーになる、という現象の回避手段にもなる。
*** Undertow(新しい WebServer )
    ハイパフォーマンスらしい。
    TecgEmpowerというサイトがあらゆるWebServerに対してリクエストを投げてパフォーマンスを計測・公開していて、
    そのランキングで上位に位置する。
    embedded版がある
*** Role based ACL
    JBossで操作できることを、ロールごとに管理できるようになる。
    Paasで使用されることを意識して、管理系機能のためのよしなしをWildfly内で完結させようとしている動きの一環。
*** Automated paching update
    今までは、このファイルを上書きして、あのコンフィグを調整して・・・・だったのを、
    zipを持ってきて、バッチ当てコマンドでベタッとやると、完了する。
*** Hibernate search
    アノテーションで対象エンティティを指定すると、
    勝手にDB内の全文検索用のindex貼ってくれる?(内部はLucene)
    激しいLikeのSQLを自前で書くよりはお手軽とか。
*** clustering
    監視リスナーを設定して、
    落ちたサーバを検知し、それを生きてるやつに知らせたり、特定のメソッドコールするよう設定できたりする。
*** Paas提供しているところ
    OpenShift / CloldBees
    Java EEのFullProfile対応しているのは上記2つだけでは、とのこと。
*** クラスタリングするときのフロントエンド側のサーバのチョイス
    [3択]: 内部的には、コアなところで同じライブラリを使っているらしい
    - mod_cluster <- 一番新しい
    - mod_jk
    - mod_proxy
*** jboss-cli
    XPath的なやり方でコンフィグ設定できる。
    生兵法でXMLを触って、壊して怪我する、ということを減らせる。
*** クラスローディングの考え方の変化
    http://www.slideshare.net/nekop/jboss-as-7-eap-6-modules-and-class-loading

    mavenの依存性推移のようなものを登録しておける。
    -> 曰く「ランタイムで利用出来るMavenみたいなやつ」
    Pros. 目的のjarをクラスローダが探しまわらなくていい
    Pros. 不要なものをロード市内で済むので若干早くなる?
    Pros. 依存性の推移先でバージョン違いのJarを使っている状態でも動ける。

*** slf4j のlog出力APIの可変長引数渡しているところで、最後の引数が例外系だったら例外としてログ出力してくれるらしい)
    事故りそうではあるが、やりたいことはできる

    JBossのLogging Managerは、log4jやslf4j側の実装を全て差し替えたものを持っている。
    アプリ側でそのライブラリを取り込んでいない状態で、logback塔を使った実装があると、
    Log4jの処理を、JBossが差し替えた版に対してリダイレクトされる。
    設定ファイルがアプリのクラスパスにあれば自動的にそれをJBossが解析して設定通りに出す。

*** その他
    - SalesforceはResinを使ってる
    - 非圧縮jarにするとサーバの起動が早くなる(展開する手間がへるよ)
    - JVM_OPTIONSに -Xverify:noneすると早い
      クラスが壊れてないか検証する、という処理を切る。
       Appletで謎のクラスを落としてきて使う、とかでなければ不要な処理だよ、という見解。
    - TieredCompilation

* Arquillianではじめるコンテナを使ったテスト (@backpaper0)
** 依存しているJarをアーカイブに含めるときは、ShrinkWrapのMavenResolverを使う方法がある
   org.jboss.shrinkwrap.resolver.api.maven.Maven

   drone
    - webdriverをinjectしたりできる
   graphere
    - droneとは違い、ajaxのテストするためにAPIを充実させたやつ
   warp
    - テストクライアント側の動作に加え、テスト対象のサーバ側の方で検証処理がかける。
      DBのテストなんかにつかえる?

* JSF アプリ作ったった ~EE サーバー載せかえ祭り~ (@shinsukeoda)
* GC (@nekop)
** パラレルGC(UseConcMargSweepGC)
   - いっぱいになったら処理を全止めして、全なめしていらないものを消す
     -> APサーバみたいなランタイム環境で突然停止とかありえない
     -> 並列でやるよ
   - UseConcMargSweepGCのチューニングについて、世のブログにいっぱい嘘、古いのが書いてあるので気をつけようね。
** JAVA_OPTSでのチューニングはデフォルトで大分いい感じなのでそれほど弄る必要はない。
   ただ、GCを始めるしきい値(占有率)が92%なので、Hadoopのような大量のアロケーションを一度に行うようなものは
   調整したほうがよい。
** Java 8はCMSが早くなったので、G1GCを使わないといけないシチュエーションは減った
** G1GCはメモリが潤沢な環境でないと無理。でもあると、停止時間累計は半分ぐらいに減らせるかも。
** GCは1GB - 1secを目安に考えておくとよい
** Zing: Azul社の有償のJavaVMでGCがちょっぱやい。(Pause less gcと呼ばれる) CPUコア数課金で、結構高いらしい。
   Linuxでしか動かない命令セットを使ってる。
** Shenandoah: Redhatがポータビリティの高い pause less gc を開発中
   「Linuxの会社なのに・・・・」「ポータビリティを損なうやつは敵、という思想がある」とか。

* EAPとWildflyの違い (@nekop)
オフィシャルはもちろん、だいたい@nekopさんのブログに書いてある話。
** Wildflyがリリースされて、チェコのテストチーム60人が3ヶ月叩いて安定させたものが EAP
** Wildflyには大きな機能リリースは反映されることがある
** Wildflyにはセキュリティパッチは基本でない
** 「有償サポートに入ると nekopさんに質問できます」

2012/12/02

「関西Javaエンジニアの会スペシャル! JavaOne2012」に行ってきた

2012/12/1に、 「関西Javaエンジニアの会スペシャル! JavaOne2012」(http://connpass.com/event/1261/) に参加してきました。 関西Javaエンジニアの会のイベントに参加させていただくのは、今回が初めてですすが、 他の勉強会で登壇されている方など、ちらほら見かけました。

勉強会の趣旨はSan Fransiscoで開催された JavaOne 2012報告会ということ、 現地の様子の展開と、その中で行われた発表内容のフィードバック、発表技術の 簡単なレクチャーといったものです。

以下、特に自分が興味惹かれたものを簡単に書いてみます。

「StrutsとTomcatをやめようキャンペーン実施中です」

寺田さん(@yoshioterada)の、「Java EE プラットフォームにおける HTML5対応」にて 表題の発言がありました。

やべぇ、俺撲滅される側の人間だわ・・・。このセッションに限らず、登壇者の話や参加者の反応について、 技術と知識と意識の落差を感じることが少なくなかった。 浅学を恥じるばかり。

JavaEE 7でアップデートされる JSF 2.2では、ビューをxhtmlというものでかけて、 htmlとしてブラウザでそのまま表示できる形でモデルとのBindをバリバリかけるよ。 デザイナさんが作ったhtmlを頑張ってJSPに治すなんてナンセンスで無駄が多いでしょ、 xhtmlをデザイナとプログラマが両方かける形でやれてハッピーになるよ、 という話。 ↓みたいな感じで、htmlとしての解釈は可能な形で埋めると。


Lambdaは書きやすいだけでなく、早くなる

さくらばさん(@skrb)による「Lambdaへの道」セッションにて行われた、 Java SE8に盛り込まれる予定のLambdaの解説。

仕事でAjaxバリバリでビューを書くことがあり、Javascriptのmap関数などで使う無名関数の強力さに触れたあと、 Javaで同じことをやろうとして、匿名クラスをモリモリ記述することの面倒くささに 打ちひしがれていたので、javaのlambdaには興味津々でした。

このセッションで、シンタックスとしてはかなり簡易にかけるということがわかったが、 それ以上に、この無名関数部分を小さい粒度で書くことでCPUのマルチコアを有効に活用して 並列処理として実行されて、処理が早くなるというのが面白そう。 どうかけば、どれだけ早くなるのか? 学習コストを越えてどれほどのメリットが生まれるのか、というのが人の多い仕事で 採用するかの鍵になるかな。 検証資料を探さないと。


新Javascriptエンジン Nashorn(ナズホン?)

寺田さんの「JavaOne 2012 のアップデート」から。

Rhinoに代わるJavascriptエンジン。 Invoke dynamicsを使うことでより高速に処理できるとのこと。

Invoke dyanamicというのは、Java仮想マシンにて動的型付け言語がサポート(...?) というように聞いたが、このあたり全く理解が追いついておらず。

これまで、私は入力バリデーションを、画面の入力チェックをJavascriptで、サーバでの検証をJavaで、 としていたけど、これがJavascriptで一本化できるだろうか、とか妄想するなどした。


NetBeansによるHTML5サポート

寺田さんの「JavaOne 2012 のアップデート」から。 NetBeans(IDE)での編集を、専用プラグインを入れたChromeに動的に反映させられる機能があり、 それがHTML5に対応するとのこと。 恥ずかしながら、NetBeansを使ったことはないので、これは試してみねば、と思っている。

※ もちろん NecoBeansも知らなかった。




以下は、さらにメモからの細かい抜粋。

  • 一時期勉強会といったらMBAの展示会みたいだったけど、タブレット + キーボードの人が結構いる
  • Project SumatraでJavaからGPGPUがかけるようになる?学習コストは安くないとみるが、一部のボトルネック処理に対するアプローチにはなりうる?
  • Jigsawは開発が遅れたため、Java SE9に順延するが、他の機能はこれを待たずに計画通りアップデートに載せていくとのこと。出来てるやつはリリースしてサイクルを早めていくという方向で進めていくということか。
  • Websocketの処理が書きやすそう。Ajax - JSONIC RestServletで書いている部分の一部置き換えに使えるだろうか。DBのアップデートをpushするという応用は特に使えるシチュエーションを妄想できる。
  • (fxmlの話を受けて)デザイナさんとの協業って今まであまりやってこなかったけど、インタフェースを使いやすくするところで質を上げたいし、タブレットスマフォだとUIへ配る意識の差は使用感が大きく変わりそう。 もっと積極的に考えないといけない。自分でもある程度UI/UXの知見がいるし、協力してやっていく場合の作業フローも考えないといけない。
  • 会の最後に寺田さんご提供のプレゼント争奪ジャンケンで敗れた。JavaOne/Dukeグッズでドヤりたかった。

最後に

Javaと長く付き合うことになりそうな立場なので、 この先Javaにどんなものが出てくるかというのを人の口から聞いてみようということで参加しました。

その意味で大いに収穫ありです。 それに、外に出て他の人がやっているものを見聞きする刺激が、 忙しいなかでもオフで何かやろうという気持ちを起こしてくれることもあります。 普段書くJavaだけに、そういうところのモチベーションを維持する点でも有意義でした。

登壇者のみなさま、コーディネータのみなさま、参加者のみなさま、ありがとうございました。

2012/09/09

PATHの通っているディレクトリのファイルを全て出力するシェルスクリプト

環境

  • OS: FreeBSD 9.0 STABLE
find で type fするとか色々あるが、手っ取り早くこれで。
PATHのコロン区切り展開が sed なあたりが特に苦しまぎれだが、 スマートな解決はあるだろうか。

2012/08/21

JavaFX2を試しつつ gistを試す

Java FX2 を動かしてみたというのはもののついでで、 gistをBloggerに貼れるかどうか試したかったがためにできた記事。

環境

  • OS: Ubuntu 12.04 (64bit)
  • JDK: 1.7.0_06 64bit

Applicationクラス

アプリケーション全体の起動ポイントかつ各種制御。

FXMLファイル

画面の構成、デザイン。CSSも適用できるらしい。Flashで言うところのmxmlか。

コントローラクラス

FXMLの制御。Flashで言うところのmxmlに対するActionScriptファイルか。

その他

  • ビルド・起動時には、${JAVA_HOME}/jre/lib/rt.ja にパスを通す
  • FXMLを相対パスで指定する場合のベースディレクトリはJavaの起動ディレクトリ。リソースファイルとかと同じ。
  • "Control"って名前のクラスにしてしまっているけど、Oracleの名づけ的にはControllerですよ。
今までは、BloggerにGoogleのprettyprint.jsを入れて、preタグの特定クラスにマークアップさせていたが、 gistの方が手っ取り早い。 資産としてBloggerに依存しないし、訂正が楽なのもよい。ので、しばらくはgistを使っていってみる。

2012/07/08

jQuery MobileでGoogleMaps使う際の覚書(地図API動的ロードと地図サイズ最大化)

ライブラリ類のバージョン

  • jQuery 1.7.2
  • jQuery Mobile 1.1.0
  • Google Maps API V3 (3.8)

覚書1: Google Maps APIの動的ロード

htmlのどこいらかで、jsapiを読み込んでおく。
<div id="scriptArea">
  <script type="text/javascript" src="http://www.google.com/jsapi"></script>
</div>
地図を読み込む局面で、jspai経由でgoogle Maps API読み込みを行う。
// Maps API読み込み状態を管理するdeferredオブジェクトを作っておく。
_maps_loaded: $.Deferred()
// 地図の読み込み終了直後に行う初期化処理を登録しておく。
this._maps_loaded.done(this.initialize_map);

// 読み込み開始、完了時にDeferredを完了状態にする。
google.load('maps', '3', {
 other_params: 'sensor=false',
 callback: function(){
     that._maps_loaded.resolve();
}});

覚書2: 地図を画面いっぱいに広げる

jQuery Mobileだと地図用のdivのwidth,heightを100%にしても広がらない模様。
$('#map_canvas').css('width', $(document).width());
$('#map_canvas').css('height', $(document).height());

// ↓は実機では未検証。
// 画面回転についていくなら、orientationchangeメソッドについていけばよい(はず)。
$(window).on('orientationchange',function(e){
});




下はテスト書きした全文。適当なオブジェクトに作り始めたけど、クラス化するか、jQuery MobileのWidget化するか、かな。
var store_map_page = {
    _maps_loaded: $.Deferred(), 
    _map_options: {},
    geos: {},
        
    map_obj: {},
    
    map_info_window: {},

    _lazy_loaded: function(){
     this.geos = {
         station: new google.maps.LatLng(34.810538,135.494923),
         yamada: new google.maps.LatLng(34.812141,135.494709),
         oasis: new google.maps.LatLng(34.811155,135.494473)
     };
     var map_options = {
         zoom: 17,
         center: this.geos['station'],
         mapTypeId: google.maps.MapTypeId.ROADMAP
     };
     this.map_obj = new google.maps.Map(document.getElementById('store_map_canvas'), map_options);
     this.map_info_window = new google.maps.InfoWindow(this.map_obj);
     _map_options = map_options;
    },

    _initialize: function (){
     var that = this;
     this._maps_loaded.done(this.map_resize, this._lazy_loaded);
     google.load('maps', '3', {
      other_params: 'sensor=false',
      callback: function(){
          that._maps_loaded.resolve();
     }});
    },

    map_resize: function(){
     $('#store_map_canvas').css('width', $(document).width());
     $('#store_map_canvas').css('height', $(document).height());
    },

    orientation_changed: function(e){
     this.map_resize();
     if(e.orientation =='portrait'){
     } else {
     
     }
    }
};

$('body').on('pageshow', function(){
   store_map_page._initialize.apply(store_map_page);
      });

$(window).on('orientationchange',function(e){
   store_map_page.orientation_changed.call(store_map_page, e);
});

$(window).resize(store_map_page.map_resize);

2012/04/04

JavaScriptオブジェクト⇔JSON文字列の変換処理時間

JavaScriptオブジェクトをJSON文字列にシリアライズ、 逆にJSON文字列からJSONオブジェクトにデシリアライズするのにかかる時間の計測結果。 オブジェクトのネストはなく、型はStringのみで、かつ一回の集計のみと、 まともな計測データの体はなしていない。 Webサービスを作るときに、やり取りするJSONのサイズにかかる ブラウザの計算量負荷を考えるにあたって、大雑把にスケールをつかんでみようかという目的で計測。

環境

  • OS: Windows7 64bit
  • CPU: Core i5 650 (3.2 [GHz])
  • RAM: 12 [GB]
  • Chrome: 17.0.963.83 m
  • IE8(64bit): 8.0.7601.17514
  • jQuery: 1.7.2.min
  • jQuery.json: 2.3.min

動作

  1. Stringの配列を作成する。配列の長さは m であり、それぞれ n 文字のアルファベットからなる文字列がセットされている、
  2. 1.で作成したStringの配列をJSON文字列に変換する。JSON.stringify or jQuery.toJSONメソッドを用いる。
  3. 2.で作成したJSON文字列を、JavaScript文字列に変換する。JSON.parse or jQuery.parseJSONメソッドを用いる。
上記の3, 4の時間を計測する。 変数の値域は下記のとおり。
  • n = 1, 2, 3, ... 10
  • m = 20, 21, 22, ..., 219

結果

各シートの記述内容
  • Chrome: 17.0.963.83 m(JSON) JSON.parse, JSON.stringifyを使用
  • Chrome: 17.0.963.83 m(jQuery)  $.parseJSON, $.toJSONを使用
  • IE8_64:8.0.7601.17514(jQuery)  $.parseJSON, $.toJSONを使用
IEが思ったより時間かかりすぎて、グラフを起こす気力がない。 10文字程度のID文字列を複数件やり取りするとして、 レスポンスを5秒以下に抑えようとすると、 IEだと4万件以下、Chromeだと27,8万件以下に抑えないとまず無理なのかもしれんなー。 まぁそんだけの量をHTTPで一度に送受信ってのもちょっと考えづらいか。

テストコード


$(function(){
        function TestCondition(recordLength, recordNumber){
            this.isCalculated = false;
            this.recordLength = recordLength;
            this.recordNumber = recordNumber;
            this.spentTime = {
                constructJsObject: 0,
                serialize: 0,
                deserialize: 0
            };
        }

        TestCondition.prototype = {
            execute: function(){
                var recordString = "";
                for(var i=0; i<this.recordLength; i++){
                    recordString += "X";
                }

                var rawJsObject = {};

                var startTime = new Date();
                for(var i=0; i<this.recordNumber; i++){
                    rawJsObject[i] = new String(recordString);
                }
                this.spentTime.constructJsObject = new Date() - startTime;

                startTime = new Date();
                var serialized = $.toJSON(rawJsObject, null)
                this.spentTime.serialize = new Date() - startTime;

                startTime = new Date();
                var deserialized = $.parseJSON(serialized);
                var deserialize = new Date() - startTime;
                this.spentTime.deserialize = new Date() - startTime;

                this.isCalculated = true;
            },

            writeResult: function(){
                var resultTable = $('#resultTable');
                var resultRecord = $('<tr></tr>');
                resultRecord.append('<td>' + this.recordLength + '</td>');
                resultRecord.append('<td>' + this.recordNumber + '</td>');
                resultRecord.append('<td>' + this.spentTime.constructJsObject + '</td>');
                resultRecord.append('<td>' + this.spentTime.serialize + '</td>');
                resultRecord.append('<td>' + this.spentTime.deserialize + '</td>');
                resultTable.append(resultRecord);
            }
        };

        for(var i=1; i<11; i++){
            for(var j=0; j<20; j++){
                var test = new TestCondition(i, Math.pow(2, j));
                test.execute();
                test.writeResult();
            }
        }

   });

JSON文字列変換後の文字長ぐらい、計算出しておけばよかった。

2012/04/02

svn:externalsをファイル単位・フォルダ単位で設定する

Subversion(ver.1.6以上)であるディレクトリ内に別のディレクトリの内容をミラーリングする、
もしくは特定のファイルをミラーリングするために、svn:externalsを使う。

たとえば、

Subversionのリポジトリ上で複数のプロジェクトを管理している。
後発のプロジェクトBが、先発のプロジェクトAと同一のリソースを常に配置したい。
そしてそのリソースはどちらのプロジェクトでも更新するし、
その反映は常に両方のプロジェクトに対して行われる。

というような状態を作りたい場合。
(そんなシチュエーション、開発の初期フェーズしか通用しないと思うけど。)

ディレクトリの参照設定


[例]

http://localhost/svn/projA/resources

を常にprojBからも参照する。

http://localhost/svn/projB/resources


#参照設定 作成
~projB$ svn propset svn:externals 'resources http://localhost/svn/projA/resources' .
property 'svn:externals' set on '.'
~projB$ svn up
Fetching external item into 'resources'
A    foo
A    bar
Updated external to revision 2.
#参照設定 削除
~projB$ svn propdel svn:externals ./resources

特定の1ファイルの参照設定

※ Subversion 1.6以降に限る。

※ 参照関係を張ることができるのは、同一リポジトリ同士に限る

subversion.apache.org subversion1.6のチェンジログ中、svn:externalsについて記述した項。

svn:forum "svn:externals" 他リポジトリへのファイル参照設定できないんだけど、というフォーラム記事。


[例]

/repo/trunk/libA/resources/shared_file.txt



/repo/trunk/libB/resources/

にから参照設定する。


libB/resources$ svn propset svn:externals '^/repo/trunk/libA/resources/shared_file.txt shared_copy.txt' .
libB/resources$ svn up
libB/resources/shared_copy.txtを編集してコミットすれば、libA/resources/shared_file.txt更新時に反映される。

逆に、libA/resrouces/shared_file.txtを編集してコミットすれば、libB/resources/shared_copy.txt更新により反映される。