getterやsetter以外のメソッドをJavaBeansのアクセッサにする
ネット上で、Java への dis として「なんで Java のプロパティアクセッサはわざわざ get/set で始まる名前のメソッドにしないといけないんだ!」というのをよく見かけます。ですが実は JavaBeans の仕様としてはいわゆる getter/setter でないメソッドもプロパティのアクセッサにすることができます。余りにも JavaBeans のことがボロクソに言われるのでかっとなって書きましたw
まずは以下の Java クラスを見てください。
/** * getter/setterを使わないJavaBeansの例. */ public class Test { private String わーい; public String すごーい() { return わーい; } public void たーのしー(String myProperty) { this.わーい = myProperty; } @Override public String toString() { return "Test{" + "わーい='" + わーい + '\'' + '}'; } }
いわゆる getter/setter がありませんね。このクラスを次のように Introspector
に掛けてプロパティを抽出し、実行してみます。
import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; /** * Beanの利用例. */ public class JavaBeansSampleApp { public static void main(String[] args) { try { Test test = new Test(); BeanInfo testBeanInfo = Introspector.getBeanInfo(test.getClass()); PropertyDescriptor[] propertyDescriptors = testBeanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : propertyDescriptors) { if ("わーい".equals(pd.getName())) { System.out.println("わーいプロパティのsetter: " + pd.getWriteMethod()); System.out.println("わーいプロパティのgetter: " + pd.getReadMethod()); pd.getWriteMethod().invoke(test, "なにこれー?"); } } System.out.println(test); } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } }
結果は次のようになります。
わーいプロパティのsetter: public void aoetk.sample.Test.たーのしー(java.lang.String) わーいプロパティのgetter: public java.lang.String aoetk.sample.Test.すごーい() Test{わーい='なにこれー?'}
set で始まっていない たーのしー()
メソッドが setter として認識され、get で始まっていない すごーい()
メソッドが getter として認識されています。プロパティの writeMethod を実行するとちゃんと たーのしー()
メソッドが実行されて値が設定されています。
からくりについて解説しましょう。次のように Bean に対応した BeanInfo
実装クラスを用意し、Bean と同じパッケージに置きます。以下の例では BeanInfo
インターフェースのデフォルトメソッドを実装した SimpleBeanInfo
クラスを継承し、必要なメソッドだけ実装しています。
/** * {@link Test}のJavaBeans情報. */ public class TestBeanInfo extends SimpleBeanInfo { @Override public PropertyDescriptor[] getPropertyDescriptors() { try { return new PropertyDescriptor[]{ new PropertyDescriptor("わーい", Test.class, "すごーい", "たーのしー") }; } catch (IntrospectionException e) { return null; } } }
ここでは getPropertyDescriptors()
メソッドをオーバーライドし、 PropertyDescriptor
のインスタンスを返しています。もうお分かりですね。ここでこの JavaBean のプロパティの情報 (プロパティ名、アクセッサメソッド) を返しているわけです。
Introspector の API ドキュメント には次のような解説が記載されています。
Fooクラスについては、情報の問い合わせ時にnull以外の値を提供するFooBeanInfoクラスがあれば、明示的な情報を取得できます。まず、ターゲットのBeanクラスの完全指定されたパッケージ名に「BeanInfo」を付加して新規のクラス名とし、BeanInfoクラスを検索します。これに失敗した場合は、この完全指定されたパッケージ名の最後のクラス名にあたる部分を使って、BeanInfoパッケージ検索パスに指定されたパッケージごとに該当クラスを検索します。
(中略)
クラスの明示的なBeanInfoが見つからない場合は、低レベルのリフレクションを使ってクラスのメソッドを調べ、標準設計パターンを適用して、プロパティのアクセス用メソッド、イベント・ソース・メソッド、publicメソッドを識別します。
(以下略)
つまり、JavaBeans を作るとき、本来は対になる BeanInfo 実装クラスを用意し、Bean の情報を提供する必要があるのです。ですが、毎回それをやっては面倒なので、便宜的にあの命名規則が用意されているわけです。CoC の先駆けだったわけですね (ちなみに JavaBeans は 20 世紀に誕生した仕様です) 。
この BeanInfo ですが次のような情報を提供することができます。
- プロパティの情報
- イベントの情報
- メソッドの情報
- アイコン
アイコンとかイベントって何?と思いましたか。JavaBeans は本来可搬性のあるソフトウェアコンポーネント、特に GUI コンポーネントを開発するために作られた規格です。つまり、IDE の「ポトペタツール」に追加して使えるソフトウェア部品を作るためのものなのです。BeanInfo ではそのツールに対して提供する情報を定義します。
こうして考えると、単なる DTO として JavaBeans を使うのはオーバースペックであることも分かりますね。なぜこんなにあちこちで JavaBeans が使われるようになったのかは歴史的な経緯が色々あるのですが、まあそれはまたの機会で。
なお、このエントリでやったいたずらは業務のコードではやらないでくださいね。いたずらに混乱を招くだけです。酒の席でのネタにとどめてくださいw
全体のコードは gist にアップしてあります。
https://gist.github.com/aoetk/e5a09f67f2ebbc206d0770b21116b69e
パーフェクトJava EEの感想
Java EE 7 に対応した解説本として出版されたパーフェクト Java EE を 著者のお一人である上妻 (id:n_agetsuma) さんから頂きました。ありがとうございます! 簡単ではありますが、本についての感想をまとめました。
実は本を頂いたのはもう半年前の夏のことだったのですが、色々と忙しい状況が続き、感想文の公開がこんなに遅くなってしまいました。ごめんなさい!
本の特色
この本の特色は、Java EE の Web Profile に内容を絞ったという思い切った点にあります。説明する対象を絞ることで、これまでの和書の Java EE 解説本よりも、各仕様の解説が深くなっており、多様な機能、意外と知られていない新機能などがしっかり網羅されています。ただ、そのために jBatch が対象から抜けちゃったのはちょっと残念だったかなと思っています。
また、著作メンバーが Oracle に近くない人で構成されているので、変にバイアスが掛かっていないというのも特色かなと思っています。いわゆる「よいしょ」的な内容が少なく、かなりぶっちゃけたことも書かれているので、実際に利用する人にとっても参考になるのではないでしょうか。
良かったと思った点
この本で特によかったと思ったのは次のような点です。
- CDI についてガッツリ解説された初めての和書です。
- Web 上の情報でもここまできっちり網羅された解説は (少なくとも日本語では) 見たことがありません。
- この点だけでも買う価値があると言ってもいいと思っています。
- 最新の JPA 仕様をきっちりカバーしています。
- 新機能である Entity Graph もしっかり押さえられています。
- JPA を利用するうえで必要とされる解説が一通り網羅されています。
- なお、これまでの和書で自分がいいと思っていた JPA 解説本は (少し古いですが) マスタリング JavaEE5 と オライリーの EJB3.1 本 です。お財布が許すのならばこれらの本も一緒に揃えておくことをお勧めします。
- Web Profile の範囲で EE6、7 で新たに追加された新機能をしっかりと押さえています。
- JTA の解説がきちんとされているのも個人的にはポイント大でした。
- そして、先行して EE8 の MVC も取り上げられている!と言いたかったところですが...嗚呼、あんなことになるなんて...。
イマイチだなと思った点
ちょっとここは良くなかったかなあと思った点も挙げておきます。
- 読者の対象に初めて Java EE を使って Web アプリケーションを開発しようとしている人が入っていましたが、その割には開発環境構築の説明が不親切だと思いました。
- 章立てが良くないと感じました。
- いきなり CDI から入るのは違和感がありました。
- 実際に作って試しながら進めてもらうには、やはりフロントから入っていくのが王道だと思います。
- JSP は省略すべきではなかった!
この本を読むべき人
以上、感じたことをつらつらと書きましたが、中々の良書だと思っています。特に次のような人にお勧めしたいですね。
Java 9で強化されたデスクトップ環境関連のAPIをJavaFXで使ってみる
このエントリは JavaFX Advent Calendar 2016 の 18 日目のエントリです。前日は id:nodamushi さんによる「 JavaFX9からPlatformに追加されるAPIについて 」でした。
はじめに
今回のエントリは JDK9 に新たに取り込まれる "JEP 272: Platform-Specific Desktop Features" を JavaFX から触ってみるというものです。
実は JDK9 では AWT/Swing/Java2D にかなり手が入ります。次のように多くの JEP が 9 には取り込まれます。
- JEP 251: Multi-Resolution Images
- JEP 256: BeanInfo Annotations
- JEP 258: HarfBuzz Font-Layout Engine
- JEP 262: TIFF Image I/O Plugin
- JEP 263: HiDPI Graphics on Windows and Linux
- JEP 265: Marlin Graphics Renderer
- JEP 272: Platform-Specific Desktop Features
- JEP 283: Enable GTK 3 on Linux
利用者に見えない内部的な強化や HiDPI 対応のような流石に対応しないとまずいものが中心ですが、その中でも JEP 272 はアプリケーション開発者側から見ても大きな機能追加になります。
まずはこの JEP 272 について紹介し、そしてこれが JavaFX からどの程度利用できるか調べてみた結果について述べていきたいと思います。
JEP 272 について
JEP 272 は "Platform-Specific Desktop Features" の名の通り、デスクトップ環境特有の機能を Java からも利用できるようにするというものです。それもプラットフォーム固有の機能も積極的に利用するというものです。
ご存じの通り Java のデスクトップ GUI アプリケーションでは、そのアプリケーションを実行するデスクトップ環境が提供している機能を利用することは中々難しかったりします。クロスプラットフォームアプリケーションの宿命かも知れません。
ですが、過去に Java 6 でそのための API が追加されたことがありました。
- 特定のファイル・タイプに関連付けられたデフォルト・アプリケーションと対話する機能を提供する java.awt.Desktop クラス。
- デスクトップ環境で設定されたデフォルトブラウザやエディタ、メーラなどを Java 側から起動することができます。
- デスクトップ環境のシステムトレイにアクセスし、アプリケーション独自のトレイアイコン、メニューを追加できる java.awt.SystemTray クラス。
システムトレイを使ったりすると、よりネイティブアプリケーションっぽくなりますよね。ですが、その後の各 OS の進化に伴い、Java から使えないデスクトップ環境の機能がどんどん増えてきました。
例えば、Windows のタスクバー、Mac の Dock では次のようにプログレスバーを表示することができるようになっています。
バッジも表示できるようになっていますね。
でもこれらの機能には Java からアクセスすることができません。
また、Mac 特有の話ですが、Mac で実行するアプリケーションでは、メニューバーにアプリケーション名のメニューが通常のメニューの左に表示されます。アプリケーションの About ダイアログや環境設定ダイアログはここから開けるようにするよう Mac 上で動くアプリケーションは統一されています。でも、Mac 特有の話なので、Java アプリケーションはここにアクセスすることができません。
JEP 272 はこういったデスクトップ環境が提供する機能へ Java アプリケーションでもアクセスできるようにするものなのです。
提供されている機能を列挙します。
- デスクトップ環境が起こすイベント (スリープ、サインアウト、フォアグラウンド/バックグラウンドの切り替えなど) に対してイベントリスナやイベントハンドラを登録する。
- タスクバーへのアクセス。プログレス表示やバッジ表示、コンテキストメニューの追加を行える。
- Mac 特有のアプリケーションメニューへのアクセス。
API レベルでは次のような追加になります。
- java.awt.desktop パッケージの追加
- デスクトップ環境で発生するイベントに対応した各種イベントクラスや、それに対するイベントリスナ、ハンドラが定義されている。
- java.awt.Desktop クラスにメソッド追加
- デスクストップ環境で発生する各種イベントに対して、イベントリスナの追加、ハンドラの登録を行うメソッドが追加されている。
- java.awt.Taskbar クラスの新規追加
- タスクバー (Mac での Dock) を操作するためのメソッドが定義されている。
この API は AWT の API です。でもこのエントリは JavaFX Advent Calendar のエントリです! なので、JavaFX からこれら機能を利用できるかを調べてみることにしましょう。
JavaFX から JEP 272 を利用する
それでは JavaFX から試してみることにします。ソースコードの全体は gist にアップしています。
https://gist.github.com/aoetk/7d5cc13e64239d1233e6dd879fed682e
Desktop クラスの利用
java.awt.Desktop
クラスを使うと、デスクトップ環境で発生する様々なイベントに対して応答することができるようになります。まずはこのクラスのインスタンスを取得してみます。
if (Desktop.isDesktopSupported()) { Desktop desktop = Desktop.getDesktop(); addAppEvents(desktop); setSystemMenuHandler(desktop); } else { System.out.println("デスクトップはサポートされていません."); }
実行している環境が Desktop
クラスをサポートしているかを確認するメソッドがあるので、どの環境でも動かせるよう、必ずこれでチェックするようにしましょう。static メソッドである getDesktop()
メソッドを使ってインスタンスを取得します。
デスクトップ環境で発生するイベントに対して応答できるようにしてみます。イベントが発生するとその旨を ListView
に表示するようにします。スクリーンのスリープを例に取ると次のようになります。
// (中略) @FXML ListView<String> displayList; private ObservableList<String> eventList = FXCollections.observableArrayList(); // (中略) private void addAppEvents(Desktop desktop) { // (中略) if (desktop.isSupported(Desktop.Action.APP_EVENT_SCREEN_SLEEP)) { desktop.addAppEventListener(new ScreenSleepListener() { @Override public void screenAboutToSleep(ScreenSleepEvent screenSleepEvent) { addMessage("画面がスリープしようとしています."); } @Override public void screenAwoke(ScreenSleepEvent screenSleepEvent) { addMessage("画面がスリープから復帰しました."); } }); } else { System.out.println("ScreenSleepEventはサポートされていません."); } // (中略) } // (中略) private void addMessage(String msg) { Platform.runLater(() -> eventList.add(msg)); }
Desktop#addAppEventListner()
メソッドを使って各種イベントリスナを登録します。画面スリープに対応するイベントは ScreenSleepEvent
になります。イベント別にサポート有無をチェック可能なので、チェックするようにしましょう。
JavaFX からの利用に当たって注意点があります。それはイベントリスナの処理は AWT のイベントディスパッチスレッドで実行されるということです。このスレッドは JavaFX のアプリケーションスレッドとは別スレッドです。従って、 Platform.runLater()
メソッドに処理をくるむ必要があります (addMessage()
メソッドの実装に注目) 。
この他にも AppForegroundEvent
(フォアグランド/バックグラウンドの変化に反応するイベント) 、 AppHiddenEvent
(Mac 特有の「アプリケーションを隠す」に反応するイベント) 、SystemSleepEvent
(システムのスリープに反応するイベント) 、 UserSessionEvent
(ログインユーザのスイッチに反応するイベント) に対するリスナをセットして実行してみました。
Mac では全てのイベントに対応しています。アプリケーション起動後、「アプリケーションを隠して復帰 -> スクリーンをスリープして復帰 -> システムをスリープして復帰 -> ユーザスイッチをして復帰」を行った結果を示します。
バックグラウンドに回ったことを検知できるのはいいですね。そのタイミングで処理を停止してリソースの消費を防いだりするようなことができますね。
Windows 環境では残念ながら SystemSleepEvent
と UserSessionEvent
にしかサポートしていませんでした。システムをスリープ、復帰させた結果を示します。
Mac のアプリケーションメニューの利用
次に Mac のアプリケーションメニューにアクセスしています。これも Desktop
クラスに対してハンドラを登録する形でカスタマイズします。まずは About メニューから。
if (desktop.isSupported(Desktop.Action.APP_ABOUT)) { // 現時点ではJavaFXでは何も起きない desktop.setAboutHandler(aboutEvent -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setContentText("オリジナルのAboutダイアログです."); alert.setHeaderText("設定"); alert.show(); }); } else { System.out.println("Aboutメニューはサポートされていません."); }
Desktop#setAboutHandler()
メソッドを使い、About メニューがクリックされた時の応答処理を登録します。オリジナルのダイアログを出そうとしたのですが...JavaFX ではそもそも About メニューの追加がされませんでした。( ;∀;)
ちなみに Swing アプリケーションで試したときはうまく動作しました。
次に設定メニューです。こちらは Desktop#setPreferencesHandler()
メソッドを使い、設定メニューがクリックされた時の応答処理を登録します。
if (desktop.isSupported(Desktop.Action.APP_PREFERENCES)) { // 現時点ではJavaFXではエラーが起きる desktop.setPreferencesHandler(preferencesEvent -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setContentText("オリジナルの設定ダイアログです."); alert.setHeaderText("設定"); alert.show(); }); }
ですが、このコードを実行すると Cocoa 側から次のエラーメッセージが返ってきました...。
2016-12-17 21:21:08.978 java[1903:815004] *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 2016-12-17 21:21:08.984 java[1903:815004] ( 0 CoreFoundation 0x00007fff88a2c452 __exceptionPreprocess + 178 1 libobjc.A.dylib 0x00007fff89405f7e objc_exception_throw + 48 2 CoreFoundation 0x00007fff88942a40 checkForCloseTag + 0 3 AppKit 0x00007fff8e19f8ce -[NSMenu insertItem:atIndex:] + 521 4 libawt_lwawt.dylib 0x00000001353c156f addMenuItem + 174 5 libawt_lwawt.dylib 0x00000001353c13f0 -[ApplicationDelegate _updatePreferencesMenu:enabled:] + 195 6 JavaNativeFoundation 0x000000013536fd60 +[JNFRunLoop _performCopiedBlock:] + 17 (以下略) )
AWT のフレームが生成されていることを前提に処理を進めているように推測されます。これはちょっと残念。なお、Swing で試したときはちゃんと動作しました。
というわけで、結論としては JavaFX では現状 Mac のアプリケーションメニューの利用はできないということになります。
Taskbar の利用
次にタスクバー (Dock) の利用を試してみることにします。バッジの表示とプログレス表示を試してみます。
if (Taskbar.isTaskbarSupported()) { Taskbar taskbar = Taskbar.getTaskbar(); if (taskbar.isSupported(Taskbar.Feature.ICON_BADGE_NUMBER)) { taskbar.setIconBadge("10"); } else { System.out.println("タスクバーのアイコンバッジへの数値登録はサポートされていません."); } addAction(taskbar); } else { System.out.println("タスクバーはサポートされていません."); }
タスクバーへのアクセスは Taskbar
クラスを通して行います。インスタンスは static メソッドである Taskbar.getTaskbar()
メソッドを使って取得します。
アイコンバッジのセットには Taskbar#setIconBadge()
メソッドを使います。Mac 環境で試すと次のようにバッジの表示に成功しました!
Windows 環境は Taskbar
クラスの利用そのものは可能だったものの、アイコンバッジの設定はサポートされていませんでした。まあ、Windows でのタスクバーアイコンへのバッジ登録が可能になったのは Anniversary Update からですしね。
次にプログレス表示を試してみます。次のように、JavaFX アプリ側のプログレス表示と、タスクバー側のプログレス表示を同時に行うようにしてみました。 AnimationTimer
を使って表示しています。
AnimationTimer timer = new AnimationTimer() { private long startTime; @Override public void handle(long currentTime) { long elapsedTime = currentTime - startTime; if (elapsedTime > PROGRESS_TIME) { stop(); progress.setProgress(1.0); startButton.setDisable(false); } else { double rateForProgressBar = Long.valueOf(elapsedTime).doubleValue() / PROGRESS_TIME; progress.setProgress(rateForProgressBar); int rateForTaskBar = (int) (rateForProgressBar * 100); if (taskbar.isSupported(Taskbar.Feature.PROGRESS_VALUE)) { taskbar.setProgressValue(rateForTaskBar); } } } @Override public void start() { startTime = System.nanoTime(); progress.setProgress(0); if (taskbar.isSupported(Taskbar.Feature.PROGRESS_VALUE)) { taskbar.setProgressValue(0); } else { System.out.println("タスクバーのプログレス表示はサポートされていません."); } super.start(); } };
タスクバーのプログレス表示は Taskbar#setProgressValue()
メソッドを使います。0 から 100 の間の数値をセットします。JavaFX のプログレスバーは 0 から 1 と違うんですよね...。
Mac で試したところ、次のように Dock 側に進捗を表示できるようになりました!
Windows は残念ながら未サポートでした。何でや、Windows7 の時からサポートしてたのに!
まとめ
というわけで JEP 272 の機能を JavaFX で試してみました。分かったことをまとめると次の通りです。
- JavaFX からも JEP 272 の機能は一部を除き利用可能。
- ただし、イベントリスナの処理は AWT のスレッドで実行される点に注意。
- Mac のアプリケーションメニューにアクセスする機能は JavaFX からは使えない。
- フル機能が使えるのは Mac だけ。Windows では一部の機能しかサポートしていない。
Mac から優先して実装されているのは理由があります。かつて Mac 環境向けの Java は Apple 自身が開発、提供しており、こういた Mac 環境特有の機能にアクセスするために EAWT という API を提供していました。
Java 7 以降、Mac 向けの Java は OpenJDK で開発されるようになりますが、この EAWT は 7、8 にはバンドルが続いていました。ですが 9 からは提供をやめることになり、代替機能を Java 側で用意することになりました。それがこの JEP 272 であるということです。
ともあれ、よりネイティブアプリケーションっぽく振る舞えるような機能が実装されたのは嬉しいことです。今後のアップデートで Mac 以外の環境向けにも実装が進んでいくことでしょう。JavaFX 向けには 10 から同等機能の実装が予定されていますが、前倒しで実装とかされないかなあ。 *1
明日は誕生日枠の id:yumix_h さんの予定です。
*1:8 の時も u40 でかなりの機能追加が入ったことがあったので
Lavie Direct HZを購入しました
携帯の PC 端末として新たに NEC の Lavie Direct HZ を購入しました。
それまで携帯 PC 端末として使っていたのは 2 年半前に購入した VAIO Tap 11 です。それが次のような理由で色々辛くなってきたので、新しい端末を探していました。
- 軽量、高解像度で、スペック的にはまずまず満足していたが、肝心の品質が悪かった。
- 無線通信する分離式のキーボードは打鍵の取りこぼしが多く、ラップトップと比べるとやはり辛い。
- トラックパッドの操作性が非常に悪かったのもフラストレーションが溜まった。
- やはり 2 in 1 という形態は中途半端だった。
そんな折、NEC のオンラインショップで 1 年前のハイエンドモデルがアウトレットで安く売られていたのをたまたま見掛けたので、やや衝動的にポチってしまいました。
この機種は「世界一軽量なノート PC」が売りのシリーズで、その中でも一番ハイエンドのモデルであったので、昨年の製品とは言え、次のように中々優れたスペックです。
- Core i7
- ディスプレイは 13 インチで解像度は 2560 x 1440 の高精細液晶
- 映り込みのないノングレア。
- Retina MBP 13 インチと同じ解像度です。
- メモリ 8GB
- ストレージ 512GB
- 薄型ラップトップでストレージ 512GB となると極端に値段が上がるものが多いので、これはお得でした。
- 重量なんと 779g!
とにかく軽いです。次の写真のように片手で楽々持てちゃいます。これに比べると MBA ですらもズシリと感じるようになります。
以下、ちょっと触ってみた感想をば。
- 良かった点
- イマイチな点
とまあこんな感じです。もし同じような機種を買おうと思っている人がいたらご参考に。とりあえず外出時のお供として 3 年くらいこれで戦えそうです。
JJUG CCC 2016 Springに参加しての感想
2016/05/21 に開催された JJUG CCC 2016 Spring に参加してきました。ちょっと遅くなりましたが参加した各セッションについて感想を簡単にまとめました。
参加したセッション
- 基調講演2: Raspberry Pi with Java
- E-3 Spring Boot で Boot した後に作る Web アプリケーション基盤
- AB-4 Introduction to JShell: The Java REPL Tool
- I-5 JavaデスクトッププログラムをふつーのWindowsプログラムのように配布・実行する方法とPCの動きが重くならないよう気を付けること
- M-6_1 十徳ナイフとしてのGradle
- I-6_2 OpenJDK コミュニティに参加してみよう
- GH-7 Java Puzzlers
基調講演2: Raspberry Pi with Java
Java エバンジェリストである Stephen Chin さんによるキーノートセッション。Stephen さんは Night Hacking Tour というのを行っていて、世界の色んな国をバイクで駆け巡り、Java を使った面白い勉強会を行っていますが、今回日本でそれを行っています。既に岡山や大阪などを回っていますが、今回この JJUG CCC で東京版を行うことになったというものでした。
内容は Raspberry Pi を使って、ファミコンのゲームコンソール (筐体の形はゲームボーイアドバンス風) を作るというもの。ソフトウェア、ハードウェアの両面から様々なハッキングを行ったという内容でとても楽しい内容でした。
ソフトウェア面では Raspberry Pi 上の Java に Java 製 NES エミュレータ halfnes を使用した点が目を引きました。オリジナルは Swing 製でデスクトップ向けでしたが、これを Raspberry Pi 向けに GUI 部分を JavaFX で作り直したとのこと! X を使わず直接フレームバッファに書き込む JavaFX の利点をアピールしていました。 *1
ボタンの数に対する GPIO の不足を左・右ボタンは同時に押さない点に着目して回避したり、3D プリンタでのヒンジの作成で様々な試行錯誤したりなど、ハードウェア面でのハックの話も面白かったです。
こう言っちゃあれかもしれませんが、Oracle にもまだこういう遊び心たっぷりな方がエバンジェリストとして残っていて良かったなあと思いました。
E-3 Spring Boot で Boot した後に作る Web アプリケーション基盤
エムスリーの吉田さんによる、Spring Boot で構築した Web アプリケーション開発について、開発環境を構築した後の開発方針についてどうしていったかについてのお話でした。
Spring Boot では開発環境構築のお膳立てをしてくれますが、その後は Spring Framework を用いたアプリケーション開発になっていきます。そこで例外処理やトランザクション設計、URL 設計、バッチ処理、設定ファイル、ログ、セキュリティといった、共通的に考慮しないといけないことをどう設計したかを説明してもらいました。
バッチ設計のところなど、所々自分の考えとは違うところはあったものの、参考になる情報が多かったです。実は近々自分も Spring Framework を久々に使うことになりそうなので、Spring については浦島状態になっている自分にはとても助かる内容でした。
AB-4 Introduction to JShell: The Java REPL Tool
Kulla プロジェクトのコミッタになった bitter_fox さん自身による JShell の解説です。今年から就活する点をちょっとアピールしてましたw
JShell でやれることを全体的にとても分かり易く説明していました。他の言語では大体あったものですが、ようやく Java にも来てくれて嬉しいです。今まで自分自身は IntelliJ の Groovy コンソールを使ってこの用途を満たしていましたが。 *2
少し驚いたのが、JShell の開発者に JavaFX Script コンパイラの作者が入っていた点です。JavaFX Script が無くなった後、こういうことをしていたのかあ。
I-5 JavaデスクトッププログラムをふつーのWindowsプログラムのように配布・実行する方法とPCの動きが重くならないよう気を付けること
高橋さんによる、Windows 環境へ javapackager を用いてパッケージングした JavaFX アプリケーションを配布する際に工夫したことを説明するというセッションです。
このセッションで取り上げられていた javapackager については手前味噌ながら自分のブログエントリでも紹介しています。
この javapackager、中々良くできているのですが、上書きインストールができない、インストールディレクトリの指定をさせることができない、など細かい点で足りないところが目に付きます。そこを Wix Toolset 側の設定に手を入れることで乗り切ったという話がとても参考になりました。
javapackager の存在については驚いた人が多かったようで、セッションの最後に沢山質問が出てきたのが印象的でした。やはりこういうものを求めていた人が多かったんでしょうねえ。*3 その割に知られていないというのが残念です。もっと Oracle はこのツールの存在をアピールした方がいいですよー。
M-6_1 十徳ナイフとしてのGradle
grimrose さんによる Gradle についてのショートセッションです。何と立ち見状態になっていて、床にべたっと座って聞く形になっちゃいました。Gradle 本当に注目を浴びてますねえ。
内容としては Gradle 徹底入門を補完するような内容になっていて、Gradle のタスクランナーとしての側面に着目し、日常のタスク処理に Gradle を活用するためのお話になっていました。特にスクリプト実行環境があまり強力ではない Windows 環境での活用を推してましたねえ。
ホットな話題である、Kotlin Gradle についても少し触れましたが、「うーん、これ嬉しいですか?」と聞いたところで場が爆笑で包まれたのが印象的でした。 *4
I-6_2 OpenJDK コミュニティに参加してみよう
OpenJDK のコミッタである久保田さんによる、OpenJDK コミュニティに参加するための最初の一歩について説明するというセッションでした。
OpenJDK のような巨大なプロジェクトになると、参加するのはとても敷居が高い印象がありますが、やはりパッチを送るのが一番良いとのことでした。ML へパッチを送るくらいならば、OCA にサインすればできるようになるようです。
多数あるリポジトリの歩き方、パッチや意見の送り先となる ML の雰囲気など、OpenJDK プロジェクトに参加されている方ならではの話が満載でとても面白かったです。
GH-7 Java Puzzlers
最後はさくらばさん、てらださんのコンビによる、Java Puzzlers のセッションでした。
Java Puzzlers と言えば、Joshua Bloch さんと Neal Gafter さんによる JavaOne の名物セッションでしたが、今や前者は Google 、後者は Microsoft に籍を移しているため *5 、行われなくなっちゃいました。
日本版はさくらばさんとてらださんコンビになりましたが、意図的なのか自然にそうなったのか、てらださんがボケ、さくらばさんがツッコミというスタイルでの進行になっていましたw
内容としては基本的な演算子やクラス、Java8 で加わったラムダ式のコーナーケースについて問うものでした。選択肢式だったこともあり、間違った理解で回答したものもいくつかあったのですが、終わってみたら全問正解は私一人という結果になっちゃいました。(^^ゞ
全問正解ということで、さくらばさん作「Java SE 7/8 速攻入門」を頂いちゃいました。ありがとうございました。
最後に
こういう技術者が集まる場に参加するのは恐らく昨年の CCC Spring 以来だったと思いますが、やはり他のエンジニアの方々と交流すると色々な刺激が得られていいですね。
非常に規模が大きくなって驚いたのですが、これを運営するのも大変だったと思います。JJUG 運営の皆様、本当にご苦労様でした。
JavaFX Maven PluginのWebサイトが復活して便利になっていた
JavaFX を Maven で開発する際に便利なプラグインとして JavaFX Maven Plugin というものがあります。これは javapackager を使ったビルド、パッケージング作業を Maven 経由で実行できるようにするプラグインです。
蓮沼さんの以下のブログエントリでも紹介されています。
NetBeans にも JavaFX 開発向けの Maven プロジェクトを作成するためのウィザードがあるのですが、こちらは Exec Maven Plugin を使って javapackager のコマンド実行をラップしただけのものです。パッケージングについても、依存ライブラリの JAR を全て解凍してから 1 つの JAR にパッケージングするようになっており、今ひとつという印象です。
この JavaFX Maven Plugin ですが、ドメインを維持することができなくなったのか、ドキュメントを載せていた Web サイトが途中で消滅してしまいました。 GitHub リポジトリの README でも Web Archive の方 にリンクが貼られているという状態ですw
ところが最近になって github.io 上に新たに Web サイトが作られるようになり、中々便利な作りになっていました。 (GitHub のコミットログを見ていると、メンテナが最初の作者とは別の人になったようで、そのことも影響している?)
http://javafx-maven-plugin.github.io/
以下のキャプチャを見てもらうと分かりますが、作りたいプロジェクトの内容を画面上でぽちぽち選択していくと、右側に pom.xml に記述すべき内容が吐き出されるようになっています。これを自分のプロジェクトの pom.xml にコピーすればいいわけです。最近こういうの増えましたねえ。
出力を JAR にするかネイティブパッケージにするか、ビルドは Maven JavaFX Plugin のゴールを直接叩くのか、それとも Maven ライフサイクルの中で実行するのか、などといった選択肢が用意されています。
以上、ちょっと嬉しかったのでお知らせまで。
Mac上のOpenJDK/OracleJDKはApple実装モジュールへの依存が残っている
はじめに
Mac OS X 向けの Java 実装はかつて Apple 自身が開発、提供していました。ですがそれは 6 で終了し、7 以降は Apple も OpenJDK に参加、OpenJDK 上で OS X 向け実装も開発されるようになり、Oralce から Mac OS X 向け JDK/JRE を提供されるようになっています。
ところが、全てが OpenJDK に移ったわけではなく、一部 Apple が実装、メンテナンスしているモジュールへの依存が残っていることを知り、ちょっと驚いたのでその内容についてまとめてみました。
Yosemite以降の新Look & FeelへのSwingの対応について
これに気付いたきっかけは、Mac OS X の UI デザインが Yosemite で一新されたことです。
Java の GUI ツールキットの 1 つである Swing は、OS の UI ツールキットが提供するコントロールを直接利用せず、Java2D を使って自分でコントロールを描画します。OS の UI ツールキットに似せた見た目にする、システム Look & Feel もありますが、これは自分で描画して似せているだけです。
さて、Mac OS X では Yosemite になって Look & Feel が一新されましたが、Swing については Swing 側が対応しない限り見た目は前のままのはずです。実際、次のスクリーンショットのように Mavericks 以前の Look & Feel のままでした。
最近、家で使っているマシンを新しく Mac mini に変えました。これには El Capitan がプリインストールされているのですが、こちらでは Swing の Look & Feel が Yosemite 以降のそれに変更されていたのです。
Java のアップデートで対応したのかな?と思って、別にある Yosemite 環境のマシンについても Java を最新版にしました。ところが、JRE のバージョンが全く同じなのに、こちらでは古い Look & Feel のままなのです (上 2 つのスクリーンショットの Java バージョン表記を確認してください) 。
これは一体どういうことなのだろうと不思議に思って、調べてみました。すると、OpenJDK の ML に次のようなスレッドがあるのを見つけました。
http://mail.openjdk.java.net/pipermail/swing-dev/2015-September/004855.html
そこでは次のような説明がありました。
The Aqua look and feel is based on the JRS library, which is provided by Apple. As far as I know the Apple provide the new "modern style controls" in the new version of JRS in OS X v10.11. You can ask additional information on java-dev mailing list at apple.com [1]
Mac OS X の Aqua 風 Look & Feel については Apple が提供している JRS と呼ばれるライブラリによって提供されているとのことです。そして OS X 10.11 (つまり El Capitan) では新しい JRS が提供され、その JRS では新しい Look & Feel に対応しているため、El Capitan でだけ Swing の見た目がアップデートされたということになります。
JRSとは何か?
JRS の正式名称は JavaRuntimeSupport になります。実体は以下の場所にありました。
/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaRuntimeSupport.framework/Versions/A/JavaRuntimeSupport
この JRS は OpenJDK には含まれておらず、ソースコードは Apple によってメンテナンス、提供されているとのことです。次の Apple の開発者向け ML にその点を説明するスレッドがありました。
http://lists.apple.com/archives/java-dev/2015/Dec/msg00007.html
これには驚きました。最初に述べたように Java 7 以降の Mac 上の Java 開発は OpenJDK に移行したはずです。それなのに、Apple 側から OS アップデートを通して提供されるモジュールがなければ変わらない部分があったということです。UI の Look & Feel に関わる部分であるため、意匠権絡みなどで移せない事情でもあったのでしょうか?
今後はどうなる?
というわけで Mac 環境における OpenJDK (Oracle JDK) には Apple 実装モジュールへの依存が残っていることが分かりましたが、少し不安なところがあります。というのも、Apple は旧 Apple Java 6 のサポートは El Capitan を最後にすると宣言しているからです。
そのため、JRS のような Apple 提供モジュールの更新も今後行われなくなる可能性があります。OpenJDK 側でもこの状況については Issue が上がっていますが、さてどうなることやら...。
[JDK-8024281] Mac OS X: stop relying on Apple's JavaVM Frameworks - Java Bug System
https://bugs.openjdk.java.net/browse/JDK-8024281
おまけ
旧 Apple Java 6 は El Capitan が最後のサポートバージョンになるとのことですが、その El Capitan 向けインストーラが Apple から提供されています。 *1
ダウンロード - Java for OS X 2015-001
https://support.apple.com/kb/DL1572?locale=ja_JP&viewlocale=ja_JP
このインストーラ、Yosemite 以前のバージョンにも使うことができます。しかもこのインストーラでインストールされる Java 6 には、El Capitan 向けの JRS がバックポートされています。よって、Yosemite にこのインストーラを使って Java 6 をインストールすると、次のように Yosemite でも Swing の Look & Feel が新デザインに変わります!