Java SE 9とJava EE 8のリリーススケジュール

Java SE 9とJava EE 8のリリーススケジュールですが、
2017/2/24現時点ではどちらも2017年7月予定となっています。


(追記)Java SE 9のリリースは2017年9月21日に延期になりました。


今年の7月は忙しくなりそうです。

JDK 9 release schedule
http://mail.openjdk.java.net/pipermail/jdk9-dev/2016-October/005092.html

2016/05/26 Feature Complete
2016/12/22 Feature Extension Complete
2017/01/05 Rampdown Start
2017/02/09 All Tests Run
2017/02/16 Zero Bug Bounce
2017/03/16 Rampdown Phase 2
2017/07/06 Final Release Candidate
2017/07/27 General Availability

Java EE 8 schedule
https://java.net/projects/javaee-spec/lists/jsr366-experts/archive/2017-02/message/0
 Public Review - Apr/May 2017
 Proposed Final Draft - June 2017
 Final Release - July 2017

Java EE 7 徹底入門と初執筆について

この記事は「Java EE Advent Calendar 2015 - Qiita」の14日目のエントリーです。
昨日は@kabaoさんで、「Javaバッチの実行環境 EEなのかSEなのか」でした。
明日はaf-not-foundさんです。


本日は、明日(12/15)刊行となるJava EE 7 徹底入門についての紹介と、私がその初執筆で感じた事について書きたいと思います。

とうとう出るよJava EE 7 徹底入門!

私が執筆を一部担当させていただいたJava EE 7 徹底入門という本が明日!(12/15)発売になります。


Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築

Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築


「とうとう」と書いたのは、この書籍の話をいただいたのが2014年10月ですので、かれこれ1年以上かかった事になります。長かったー(>_<)!


本書は、日頃Javaコンサルタントをしているメンバーで、Java EEを始めて学ぶ方、またはこれから開発をJava EEに移行しようと考えているアーキテクトの方を対象にJava EEの全体像を理解してもらうことを目的に書きました。全体像とは言ってもJava EE 7の全仕様を満たしたものではなく、その中で重要だと思われるJSF,EJB,CDI,JPA,JAX-RS,JBatchについて詳細に解説しています。各章立ては以下のようになっています。(全10章)


Chapter 1 Java EEの基礎知識
Chapter 2 プレゼンテーション層の開発――JSFの基本
Chapter 3 プレゼンテーション層の開発――JSFの応用 その1
Chapter 4 プレゼンテーション層の開発――JSFの応用 その2
Chapter 5 ビジネスロジック層の開発――CDIの利用
Chapter 6 ビジネスロジック層の開発――EJBの利用
Chapter 7 データアクセス層の開発――JPAの基本
Chapter 8 データアクセス層の開発――JPAの応用
Chapter 9 RESTful Webサービスの開発
Chapter10 バッチアプリケーションの開発


私が担当したのは2〜4章のJSFの部分です。Java EE 7の仕様は膨大で、一冊の本にすべて収めることは困難です。今回は本全体を通して簡単なサンプルアプリを1つ作成し、その中で利用可能なアーキテクチャを中心に説明するという方針をとりました。(JSFの章については使用していない機能もけっこう突っ込んで記載してしまいましたが...)


JSFの2〜4章でだいたい150ページくらいでしょうか。当初の予定では80ページくらいに抑える予定でしたが、書きたいことを書き切ったら結局1章分増えてしまいました。なるべくノウハウなども詰め込んで記載したつもりなので、これからJava EEを始める方の参考になればと思っています。

執筆ってどうなの?初執筆で感じた感想

今回の「Java EE 7 徹底入門」は私にとって初めての執筆でした。当初は執筆に興味はありましたがどのようなスケジュールで刊行まで進むのか全くわからず、興味半分、不安半分という感じでした。

思っていた通り大変でした

想定はしていましたが予想通り大変でした。今回の執筆はプライベートでの執筆なので土日を使って作業しましたが、計算では150ページの本を書こうとすると本のサイズにもよるらしいですが本書だとだいたい1ページ1000文字くらい必要になります。だいたい1日頑張っても10000文字くらい書けるかどうかという感じなので2ヶ月近いの土日がすべてなくなってしまいます。実際は1日そんなに書くことはできず「数時間検証作業をして、15分記載」のような繰り返しが続くのでさらに時間を割いたと思います。特に妻子持ちの私としては土日が潰れると家族の不満もたまってくるのでそのバランスを取るのもとても大変でした。

想定外にかかるその他の作業

文章の校正作業というのをまったく意識していませんでしたが、かなり時間がかかりました。レビューの指摘で1項まるまる書き直したり、自分の書いた章を校正するだけでも一字一句丁寧に確認する必要があるので150ページあると普通に1日かかったりしていました。(校正作業中は書き過ぎたのをかなり後悔していました)またサンプルコードの整理や、章と流れをあわせるために他の章も一通り目を通すなど想定外の作業がけっこうありました。

なんだかんだで良い経験となりました

振り返ると大変さしか思い出しませんが、結果として大変多くの新しい経験と知識を得ることができてとても良い経験となりました。このような機会をいただけてとても感謝しています。ありがとうございました。


Java EEをこれからはじめたいと思う方は是非「Java EE 7 徹底入門」を手にとっていただければと思います。


Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築

Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築

JSFのバリデーション

この記事は「Java EE Advent Calendar 2014」の22日目のエントリーです。
昨日は@suke_masaさんの「続・JPQLでハマった話」でした。明日は@kikutaro_さんです。


今日はJSFのバリデーションについて整理したいと思います。

JSF1.*時代のバリデーション

JSF1.*の時代にはFaceletsのValidateタグを使用してバリデーションを行っていました。例えば5文字以上10文字以下の文字数のチェックを行うプログラムは以下です。

・facelets

<h:form>
  <div>
    <h:inputText id="msg" value="#{hogeBean.msg}">
        <f:validateLength minimum="5" maximum="10" />
    </h:inputText>
    <h:message for="msg" />
  </div>
  <h:commandButton action="#{hogeBean.exec}" value="Exec" />
</h:form>

初期のJSFは画面の作成をGUIで行っていました。そのためバリデーションの設定も画面に持つ事でプロパティで簡単に設定を行う事ができました。

JSF2.0以降のバリデーション

Java EE 6に導入されたJSF2.0からはバリデーションにBean Validationが使えるようになりました。Bean Validationを使用することでJPA等のバックグランドのチェック処理とJSFのチェック処理を共通化出来ます。Bean Validationのチェックは画面側では行わずEL式で紐づくバッキングビーン側のフィールドにアノテーションで設定します。

・バッキングビーン

@Named
@RequestScoped
public class HogeBean {
    @Size(min = 5, max = 10)
    private String msg = "Hello!";
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public void exec() {
    }
}

JSF2.0からは設定より規約が重視されるようになり、GUIに頼らずコードベースで簡単に開発出来るようになりました。そのため、特に画面側にバリデーションを持つ必要性は無くなりました。

Bean Validationでnullチェック出来ない問題

JSFのチェックをBean Validationで行うとすると最初に@NotNullが使用出来ないという問題に遭遇します。具体的には以下のようなソースでは未入力チェックが出来ません。

・バッキングビーン

public class HogeBean {
    @NotNull //未入力チェック出来ない
    private String msg = "Hello!";

これは画面の入力項目がnullではなく空文字として設定されるため発生します。

対処法1 空文字対応のチェックアノテーションを使用する

対処法の1つ目は@NotNullではなく空文字にも対応したアノテーションを使用する事です。たとえばHibernate Validatorで提供されている@NotEmptyを使用すると空文字の場合もエラーにする事が出来ます。

・バッキングビーン

public class HogeBean {
    @NotEmpty //未入力チェック出来できる!
    private String msg = "Hello!";

ただし、@NotEmptyを使用するとJava EE標準ではない実装アノテーションにソースが依存する事になります。

対処法2 INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULLを指定する

web.xmlのコンテキストパラメータにINTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULLを設定すると、サブミットされた値が空文字であった場合に,JSF内でnullに変換してくれます。そうする事で@NotNullで未入力のチェックを行う事が出来ます。

・web.xml

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

・バッキングビーン(@NotNullのまま)

public class HogeBean {
    @NotNull //未入力チェック出来きる!
    private String msg = "Hello!";

相関チェック

JPAではエンティティを引数に渡すと設定してあるチェックは一通り実施してくれますが、JSFではEL式でフィールド単位に紐付けを行うため単項目チェックしか実施されません。対処法はいくつかありますが、今回はBean Validationで2つの項目が同じ値でないとエラーとなるバリデーションを作成してみます。

・Bean Validation用アノテーション

@Documented
@Constraint(validatedBy = {EqualsValidator.class})
@Target({FIELD})
@Retention(RUNTIME)
public @interface Equals {
  String message() default "同じ値ではありません";
 
  Class<?>[] groups() default {};
 
  Class<? extends Payload>[] payload() default {};
 
  String value();
 
  @Target({FIELD})
  @Retention(RUNTIME)
  @Documented
  public @interface List {
    Equals[] value();
  }
}

・Bean Validation実装

public class EqualsValidator implements ConstraintValidator<Equals, String> {
 
    private String target;

    @Override
    public void initialize(Equals equals) {
      target = equals.value();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        UIComponent currentComponent = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
        if (currentComponent != null) {
            //同階層にあるUIComponentを検索
            UIComponent component = currentComponent.getParent().findComponent(target);
            if (component != null && component instanceof UIInput) {
                UIInput uiInput = (UIInput) component;
                Object targetValue = uiInput.getSubmittedValue();
                //SubmittedValueがnullの場合は検証後のデータを取得
                if(targetValue == null) {
                    targetValue = uiInput.getValue();
                }
                //指定された項目と同じ値かをチェック
                if (value == null) {
                    return targetValue == null || targetValue.equals("");
                } else {
                    return value.equals(targetValue);
                }
            }
        }
        return true;
    }
 
}

・利用例(サーバ側)

public class TestData implements Serializable {
    private String val1;
    @Equals("val1")
    private String val2;

・利用例(画面)

<h:form id="form">
    <h:inputText id="val1" value="#{checkBean.testData.val1}" /><h:message for="val1" /><br />
    <h:inputText id="val2" value="#{checkBean.testData.val2}" /><h:message for="val2" /><br />
    <h:commandButton action="#{checkBean.check()}" value="送信" />
</h:form>

・実行結果
f:id:den2sn:20141221102913p:plain

val1とval2が同じでないとエラーになります。
なんとか作成できましたが、JSF依存の実装で、かつコンポーネントの配置やIDを意識する必要があるので微妙な作りとなってしまいました。JSFの正式対応が望まれます。*1

*1:Java EE 8で<f:validateWholeBean>タグが導入されました

GlassFish4.1リリース!

本日GlassFish4.1がリリースされました。
GlassFish Server Open Source Edition 4.1 Released! (The Aquarium)


同時にNetBeansの8.0.1もリリースされています。
もちろんGlassFish4.1がバンドルされています。
Welcome to NetBeans


GlassFish4.0はかなりバグを含んでいたので
これでかなり改善するんじゃないかと思います。

3ヶ月経ちました

日本オラクルに入社して3ヶ月が経ち、今月から無事正社員となりました。


やっと新しい環境にも慣れてきて、これからはさらに一歩踏み出した活動が出来ればなと思っていたりします。
直近はコンサルスキルの向上と1〜2年で達成する事を明確にするところからですね。


今は製品導入もやりつつJava EE導入のコンサル活動をやっています。
Java EEの導入で問題を抱えてる人がいれば気軽にお声がけ頂ければ相談に乗れると思います。

Java 8でJavaScript。スクリプトエンジンでNashornを試す

やや気が早いですが、Java 8のEarly Access版でお試し。
Nashornネタあまり出てこなそうなのでとりあえずスクリプトエンジンの復習です。


スクリプトエンジンはJava 6で導入された機能で、JavaVM上でJavaScriptRuby等のスクリプト言語が実行出来ます。特にJavaScriptJDKの中に実行エンジンが含まれているため、追加のライブラリ不要で使えるのがポイントです。Java 7でインボークダイナミックという機能が導入されJavaの中でスクリプトがより効率よく実行出来るようになりました。そして、Java 8でそのJavaScriptの実装がRhinoからインボークダイナミックを使ったNashornに置き換わります。つまり、よりJavaの中でJavaScriptが効率的に実行出来るようになるという事です。


では、とりあえずmainメソッドにソース書いてみます。

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.eval("print(1+2);");


実行してみましょう。

3


わずか3行でJavaJavaScriptが動きますね。
うーんやっぱりJavaJavaScriptが動くのは不思議な感じ。
ちなみにengineのクラス名をSystem.outで出力してみると。

jdk.nashorn.api.scripting.NashornScriptEngine@6279cee3


確かにNashornになってます。


JavaからJavaScriptのfunctionを呼び出したい場合はScriptEngineクラスをInvocableにキャストすると呼び出せます。JavaScriptの「hoge」ファンクションをJavaから呼び出してみましょう。

engine.eval("function hoge(a,b){return a+b;}");
Invocable invocable = (Invocable) engine;
Object object = invocable.invokeFunction("hoge", 1, 2);
System.out.println(object); //3


キャストというのが少し微妙ですが、JavaからJavaScriptのfunctionが呼び出せて、JavaScriptからの戻り値もJavaで受け取る事ができます。


また、JavaScript内でJavaのクラスも扱えます。JavaScript内でLocalDateクラスを呼び出してみます。

engine.eval("print(Java.type('java.time.LocalDate').now());"); //2014-03-07


上記を実行すると今日の日付が出力されます。RhinoでimportPackage(またはimportClass)ファンクションを使用していましたが、Nashornは使用出来なくなっているので注意が必要です。どうしても互換性の為に使用する必要がある場合は、互換性スクリプトを事前に読み込む事で対応できます。

engine.eval("load('nashorn:mozilla_compat.js');importPackage(java.time);print(LocalDate.now());"); //2014-03-07


スクリプトエンジンはJavaの内部で簡易に記述出来るスクリプトが利用出来るほか、スクリプトで作成されたライブラリ資産がJavaで利用出来るようになるため、使い方によってはとても面白い事が出来ると思います。