SpringMVC良さげ感

学校のプロジェクト演習の授業でWebアプリ作ろうとしてるけど、何を使うか色々試してる。
JavaEE7でJSF+PrimeFaces使ってるけど結構不満な点がいくつか出てきた。
例えば/app/project/1/dashboard.jsfみたいなURLを使いたいって時に/app/project/{projectID}/dashboard.jsfみたいな感じにできない。
できるかもしれないけど方法見つけられなかった。
じゃあGET使うかってことで/app/project/dashboard.jsf?projectID=1ってすると、とあるプロジェクト一覧のとあるタスクページを見ようとした時にこうなる。
/app/project/ticket.jsf?projectID=1&ticket=2
これが気に食わない感じ・・・

今日うらがみがJavaまわりのWebフレームワークを知りたい会行ってきて色々話し聞いた感じSpringMVCがよさ気だった。

コード例としてはこんな感じ

@Controller
public class SayHelloController {
    @RequestMapping("/hello/{name}")
    public String sayHello(@PathVariable("name") String name, Model model) {
        model.addAttribute("name", name);
        return "hello";
    }
}

やりたいことが解決出来たねやったね。
テンプレートエンジンにThymeleaf使えばデザイナも多分苦しまないだろうし、こっち使えば問題解決だし乗り換えるかな?
けどPrimeFacesなくなるからajax自分で書かないといけなくなるんだよね。JS書くの苦手だから出来る限りフレームワークに頼りたさある。
Springいろいろ試してみてから移行考えてみることにする。

JJUG CCC行ってきた

人が多かった。
参加者が1000人超えてるとかで東京のイベントの規模の大きさに驚いた。

いくつかセッション見てきて、面白かったのがgroovy
groovy、思った以上に良い。Gradleのbuild.gradleでなんとなくで書くくらいしか使ったことなかったけど、XMLの操作やエクセル操作がかなりやりやすそう。
JavaSEでそういった操作をしようとしたら結構面倒なので、これからgroovyで書くって感じでも良さ気だなと思った。

GS CollectionsのセッションはJDTの時より詳しくやってた。とりあえずGS Collections Kataをクローンして始めようと思ったけど、とても時間かかってる。クローンできたらまた別の記事で紹介します。

とりあえず7日から12日の今日までのそこそこ長い期間東京にいて疲れたので休みたい。
某氏に秋も来るよね?って圧力かけられたけど多分行けないと思います。

JavaDayTokyo2015行ってきた

日本のJavaオタクのお祭りのJavaDayTokyoに行ってきました。
JavaDayTokyoに参加するのは初めてなんですが、今年はJava生誕20周年ということでかなり気合がはいっていたそうです。

前日の夜から東京に入ってイベントに向かったのですが、イベント開始が9時半ということで通勤ラッシュにぶつかって見事に遅刻しました。
基調講演最初から見たかったなぁ・・・


基調講演

基調講演の会場がこんな感じ。3階席からだとステージよく見えない・・・。
2015-04-08 10.24.07

ソフトバンクの店員で有名なペッパー君のSDKの話やJavaCarのデモとかの話やってました。
Java SE 9は来年あたりらしいという話もでてました。


昼飯

基調講演終わった後はnoko氏が近くにいたので一緒に昼食を食べたあとJavaグッズとオライリー本を買いに行きました。
Tシャツ2枚とJavaリュック・Dukeマグカップを購入。今年はJavaリュックとTシャツでキメるのが熱い!
写真とったけど、なぜかアップロード出来ないのでまた後日。

展示ブースではサムライズムでシールを頂きました。


Lambdas and StreamsAPI

午後最初のセッションです。
ここでうっかり休憩時間が13時30分まであると勘違いしていて20分ほど遅れて見ることになりました・・・。
内容的には、これからStreamAPI始めようとしている人向けという感じのセッションだったので、後半から聞いてても問題ない感じでした。


ゴールドマンサックスのJavaへの取り組み

午後2コマ目のセッションです。
関西のイベントの懇親会できつねさんに「ゴールドマンサックスすごいよ」といった話を聞いていたのでいってみました。
会社の話はそんなに無くて、GS Collectionsというライブラリの話が中心でした。

スピーカー曰く「StreamAPIを超えるライブラリだ!」とのこと。
学習環境も充実していて、プロジェクトのテストケースを通していく形で学習できるとか。
リポジトリは多分これ
GS Collectionsに関しては実際触って改めて記事かくと思います。


Nashorn in the future

午後3コマ目のセッションです。
Nashornのバージョンアップとかの話だった気がする・・・。あまり頭に入ってないごめんなさい


CDI and EJB – JavaEE alignment and strategy

午後4コマ目のセッションです。
最近JavaEEも触り始めたので行ってみました。
EJBとCDIのどちらを使えばいいか、どのような役割をもっているのかといった感じのセッションでした。

聞いた感じの僕なりの解釈ですが、JSFとEJBの間のレイヤーとして使うといった感じっぽい?


Java and The Internet of Things For Automotive Applications

最後のセッションです。
Javaを使って車やセンサーから得られる情報を表示するハードを作った話でした。
ハードの制御まで手をだすと色々とやれることが広がるので、僕もやってみたいと思いました。
とはいえ実際手を出すとお金が溶けそうだ。


20周年記念セッション

弁当と飲み物と解答用紙が配られて、弁当を食べながらJavaのクイズを答えたりする感じのセッションでした。
最初のJavaの前の名前は何?(答え:Oak)とかは答えられたんですが、3・4問目あたりからはもうさっぱりでした・・・


JavaDayTokyo Night Party

JavaDayTokyoが終わってからは会場を移動してナイトパーティーがありました。
Dukeのケーキ登場が出たり、Javaパフォーマンス本(寺田さんとcero_tさんのサイン付き しかもかわいいDukeのイラスト付き!)を頂きました。
これも写真とったけどアップロード出来ない・・・。また後日貼ります・・・。

次の記事は11日にあるJJUG CCCの記事になると思います。

JavaFXのListCellで非同期処理して失敗した話

Javaビーム工房のタイムラインにListView使っているんだけど、画像の表示やリプライ先の表示とかで非同期処理して表示するセルがずれる問題があった。(というか今も現在進行形で発生してる
その原因がListCellの中で非同期処理してるのがまずい。
どんなことが起きているかというと、リプライ先表示で説明するとこうなる。
リプライ先取得開始(非同期処理開始)→新しいツイートが来て表示するべきオブジェクトが変わる→新しいツイートのリプライ先はキャッシュされていたので先に終了→遅れて最初のリプライ取得終了→上書きされてずれる

解決方法としては、現在ListViewのItemsに入れている型がStringとかのフィールドを持つクラスなんだけど、これとは別にPropertyのフィールドだけを持つクラスを作成して、それをItemsに入れるのが良いと思う。これならプロパティが変更された時にListCellで変更を検知して表示内容を変えれる。きっとこれで解決のはず!

簡単なサンプルとしてプログレスバーを表示するListViewのサンプルを作った。
間違いや他の解決方法アレば教えて下さい。

Minecraft1.8サーバープラグイン開発 データベース編

イベント編の続きです。
今回はデータベースを使ってプレイヤーのログインのログをとってみます。
データベースはMySQLを使用しています。

データベースといえばJPAを使用したかったんですが、試行錯誤してもダメでした。
理由としてはMETA-INF/services/の中にあるファイルを読み込めないのが原因のようでした。
というわけでBukkitで用意されているEbeanを使用していきます。

まずMySQLを使用するために依存関係にcompile ‘mysql:mysql-connector-java:5.1.34’を追加します。
次にplugin.ymlにdatabase: trueを追加。これを行うことでデータベースを使用できるようになります。

Ebeanで使用するためのエンティティを作成します。
JPAと同じでjavax.persistence.Entityアノテーションをクラスにつける感じで。
また、デフォルトコンストラクタとゲッタ/セッタが必要です。

@Entity
@Table(name = "PLAYER_JOIN_LOG")
public class PlayerJoinLog {
    @Id
    @GeneratedValue
    private Long id;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false)
    private Date joinDate;

    @Column(nullable = false)
    private String playerName;

    @Column(nullable = false)
    private String playerUUID;

    @Column(nullable = false)
    private String joinIP;

    //コンストラクタとゲッタセッタは省略
}

PluginクラスでgetDatabaseClassesメソッドをオーバーライドしてデータベースで使用するエンティティのClassクラスのリストを返します。

@Override
public List<Class<?>> getDatabaseClasses() {
    return Arrays.asList(PlayerJoinLog.class);
}

onEnableされた時にテーブルの存在を確認し、テーブルを作成します。

private static EbeanServer database;
@Override
public void onEnable() {
    setupDatabase();
}

private void setupDatabase() {
    try {
        getDatabase().beginTransaction();
        getDatabase().find(PlayerJoinLog.class).findRowCount();
    } catch (PersistenceException ex) {
        installDDL();
    } finally {
        getDatabase().commitTransaction();
    }
}

public static EbeanServer getPluginDataBase() {
    return getPlugin().getDatabase();
}
public static Plugin getPlugin() {
    return getPlugin(ServerPlugin.class);
}

ListenerでPlayerがログインした時DBに情報を保存しましょう。

@EventHandler
public void onLogin(PlayerJoinEvent event) {
    Player player = event.getPlayer();
    UUID uuid = player.getUniqueId();
    PlayerJoinLog log = new PlayerJoinLog(player.getPlayerListName(), uuid.toString(),
            player.getAddress().getHostName());

    EbeanServer dataBase = MyPlugin.getPluginDatabase();
    try {
        dataBase.beginTransaction();
        dataBase.save(log);
    } finally {
        dataBase.commitTransaction();
    }
}

後はビルドして動作を確認して終了です。
このプラグインを使うためにはBukkit側で設定が必要になります。

実際動かすjarと同じディレクトリに生成されているbukkit.ymlに以下を記述します。

database:
  username: DBのユーザー名
  isolation: SERIALIZABLE
  driver: com.mysql.jdbc.Driver
  password: DBのパスワード
  url: DBのURL

これで設定は以上です。


おまけ

IntelliJでDBの設定(Ultimateの機能だけど)

追加からMySQLを選択
DatabaseTool1

ホストとポート、データベース名とユーザー名パスワードを入力
TestConnectionで接続確認をとれたらOK
DatabaseTool2

データはこのような形で見れるようになります。
データをダブルクリックで編集できます。
DatabaseTool3

SQL文はデータベースかテーブルを右クリックしてConsoleを選ぶと入力用のタブが開くのでそこで入力して実行。
補完めっちゃきいて良い感じです。
実行結果はこんなかんじで表示。
いいですね。IntelliJ
DatabaseTool4

Minecraft1.8サーバープラグイン開発 イベント編

HelloWorld編の続きです。
今回はイベントを使用してログインしてきたプレイヤーにかぼちゃをかぶせるプラグインを作成してみましょう。

Bukkitではサーバーで発生したいろいろなイベントを受け取る仕組みが用意されています。
これを使用することで一定範囲のブロックを破壊できないようにしたり、ログインしてきたプレイヤーにアイテムをプレゼントしたりなどの処理を行えます。

イベントを受け取るリスナはorg.bukkit.event.Listenerインターフェイスを実装します。
Listenerインターフェイスはマーカーインターフェイスになっていて実装しなければいけないメソッドはありません。
イベントを受け取るメソッドはorg.bukkit.event.Eventを継承しているクラス1つを引数に取り、@EventHandlerアノテーションがなければいけません。
引数のクラスによってメソッドは適切なタイミングで呼び出されるようになります。

プレイヤーがログインした時にかぼちゃをかぶせる処理を書いてみます。

public class MyListener implements Listener {

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        player.getInventory().setHelmet(new ItemStack(Material.PUMPKIN));
    }
}

非常に簡単ですね。
最後にこのMyListenerをBukkitに登録する必要があります。
registerEventsには第一引数にListener、第二引数にPluginを与えます。

public class HelloWorld extends JavaPlugin {
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(new MyListener(), this);
    }
}

イベントは独自で定義することも可能です。
複雑なプラグインを作ったりする場合は使うことになると思います。
独自のイベントを作成する場合はEventを継承し、staticなHandlerListを宣言します。
親に定義されているgetHandlersメソッドをオーバーライドしてHandlerListを返すようにします。
追加でHadlerListを返すpublic static HandlerList getHandlerList()を作成します。
これを用意しないとIllegalPluginAccessExceptionが発生します。

イベントを通知する場合はBukkit.getServer().getPluginManager().callEvent(customEvent);のようにcallEventメソッドを使用します。
リスナは@EventHandlerアノテーションのつけられたメソッドで引数にCustomEventを定義するだけです。

これでイベント編終了です。

Minecraft1.8サーバープラグイン開発 HelloWorld編

前回の続きです。
とりあえずHelloWorldでもやってみる。

まずはsrc/main/resources/にplugin.ymlを作成
これはサーバーがプラグインを読み込んだ時に必要な情報をこのファイルからロードします。
必須の項目はname, version, mainの3つです。
nameにはプラグインの名前を文字列で記述します。
versionにはプラグインのバージョンを文字列で記述します。
mainにはJavaPluginクラスを継承したエントリポイントとなるクラスを完全修飾名で記述します。

その他の設定についてはWikiを参考にすると良いと思います。

エントリポイントとなるクラスはJavaPluginクラスを継承します。
プラグインが有効化された時onEnableメソッドが呼び出されるので、プラグインの初期化はonEnableで行います。
コマンドなどでプラグインが無効化された時はonDisableメソッドが呼び出されるので、イベントリスナやタイマー処理はここで終了するようにしておきましょう。

今回は有効化された時にHelloWorldするだけにしておきましょう。

public class HelloWorld extends JavaPlugin {
    @Override
    public void onEnable() {
        System.out.println("HelloWorld!");
    }
}

JPAのエンティティクラスでなぜプリミティブではなくてラッパーを使うの?

by orekyuu 0 Comments

最近学校の作品制作をするためにJavaEEを勉強し始めた。
JPAいじってて疑問に思ったんだけど、値にプリミティブとラッパーどちらでも使えるようになっていて、どちらを使えばいいのか分からなかった。サンプルとかいろいろ見てるとラッパーばかりだったので僕もそれに合わせてたけど、計算するときとかプリミティブに直すしBoxingするだけ無駄じゃないかと思って理由を調べたら結構見つかった。

Should I use Primitives or wrappers in JPA2.0?

理由としてはラッパーの場合は設定されていない値としてnullを扱える。プリミティブなら0やfalseなどの値になる。
EntityManagerの管理下出ない場合はnullになる。

ということらしいです。確かに値が0であれば値が空なのか0が保存されているか分からないですね。
他に使う理由があったり、プリミティブ使ったほうが良いという理由とかあれば教えて下さい。

Minecraft1.8サーバープラグイン開発 開発環境構築編

Bukkitの開発が止まってしまって1.8のプラグイン開発できないなーと思ってたんですけど、Spigotが1.8対応しているみたいだったのでそれで開発してみようと思います。

まずは本体やらを準備しないといけないんですが、自分でビルドを行う必要があります。
公式サイトのDownloadsからBuildTools.jarをダウンロードします。
適当なディレクトリに投げてjava -jar BuildTools.jarのようにjarを実行すればビルドしてくれます。

必要なものが用意できたら、build.gradleを用意します。

ビルドパスにbukkitとspigot-apiを入れたいのでcraftbukkit-1.8.jarとspigot-api-1.8-略.jarをlibsフォルダに入れます。
基本的にspigot-apiのクラスを使用するのですが、Databaseの機能を使いたいのでbukkitも一緒に入れています。必要なければ入れる必要はないと思います。
jarタスクは誰か添削頼みます。groovy力が足りない・・・!じゃけんあとで勉強しましょうね~

開発環境は整いました。おしまい。
気分が乗ったら続き書くと思う。

PrimeFacesが最高すぎる件

by orekyuu 0 Comments

Playframeworkやっぱりやめましたってなった理由がajaxの面倒臭さだったんだけど、JSFでPrimeFacesを使うとすごい楽になった。

Messagesとかはよく使うと思うので非常にやりやすい。
使い方はMessagesにautoUpdate=”true”をつけて、コード側でaddMessageするだけっぽい(?)

こういったものを自分で書かなくて良いのはすごい捗る。良い。
その他のコンポーネントも充実してるので捗りそう。

見た目はhttp://primefaces.org/themesに揃ってるっぽい。