2011年に読んだ本

すでに1月も終わりに使いのですが、、昨年、読んだ(買った)本とともに昨年の活動を振り返ってみたいと思います。途中になっている本もかなりあります。あとは雑誌で会社にあるSoftware DesignとWeb+DBプレスを読んでます。

Java

引き続きサーバ側はJavaを使っています。JAX-RSでJSONを返しクライアントはextjsなどJavaScriptを使う組み合わせが多いです。Javaであまり新しいことに取り組んていないですが、OSGiとPlay frameworkを少しかじりました。実用レベルにはまったく至っていないです。

Scala

今年はPlay + scalaで二兎を追ってみたいと思います。。書籍としては第2版も出たのでスケーラブルScalaだけでよいという印象です。

Android

趣味でやってました。結局アプリをマーケットに公開するには至っていないのですが今年は仕事でも使いたいです。Titaniumもかじってました。

JavaScript

JavaScriptはjQuey, ExtJS, Sencha Touchあたりを使っていました。スパゲッティになってしまうことが多いのでJavaScriptでもう少し綺麗な設計・コードを書けるようにしたいです。あとはJavaScriptのテストコードを書く習慣がついていないので、テスト駆動JavaScriptを読んでいるところです。これとJavaScriptパターンがおすすめかなと思います。

まとめ

本を読むのもいいけど、もっと手を動かそう、というのが今年の目標です。

IEでselect要素のchangeイベントが発生しない場合の対応

セレクトボックスが変更されたら、連動して別の要素を更新するということをしますが、SeleniumでこれをテストするとIEのみchangeイベントが発生しないようです。この場合は、以下のようにSeleniumから強制的にイベントを発生させます*1

// IEでイベントが発生しない
selenium.select("selectId", "value=foo");

// jQueryの場合
selenium.runScript("$('#selectId').trigger('change')");

// NG
// selenium.fireEvent("selectId", "change")

*1:これだとIE以外では複数回イベントが発生してしまいますが

Jerseyで@RolesAllowedアノテーションを使った認可の設定

JAX-RSでは、権限のあるユーザのみリソースにアクセスすることを可能にするために、アノテーションによる宣言型の記述とプログラマティックな処理をのためのAPIがあります。アノテーションを使う場合には、特定のロールを持つユーザのみ許可するのであれば、以下のように@RolesAllowedアノテーションでロールを記述します。

@Path("/myResource")
@RolesAllowed("admin")
public class MyResource {
	@GET
	@Path("{id}")
	@Produces(//...)
	public String get(@PathParam("id") int id){
		// ...
	} 
}

実際のロールの確認は、HttpServletRequest#isUserInRole()が呼び出されるので、認証やロールの設定はコンテナで行なっておく必要があります。
今回この設定を試すにあたって引っかかった点としては、コンテナがJavaEE6対応でない場合には(Tomcatなど)、web.xmlに設定を追加しないとアノテーションが処理されません。以下のようにServletのinit-paramにてRolesAllowedResourceFilterFactoryを追加します。

<servlet>
	<servlet-name>Jersey REST Service</servlet-name>
	<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
	<init-param>
		<param-name>javax.ws.rs.Application</param-name>
		<param-value>com.azuki3.sample.jaxrs.config.MyApplication</param-value>
	</init-param>
	<init-param>
		<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
		<param-value>com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory
		</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

参考

RolesAllowedResourceFilterFactory (jersey-bundle 1.11 API)

JavaによるRESTfulシステム構築

JavaによるRESTfulシステム構築

extjsのGridPanelで動的に列を追加する

最新のextjs 4ではなく3.4です。

// GridPanelを生成
var grid = new Ext.grid.GridPanel({
    // config options for GridPanel here ...
    columns: [{
        {id: 'name', header: 'Name', width: 200, sortable: true, dataIndex: 'name'},
        {id: 'email', header: 'E-mail', width: 300, dataIndex: 'email'},
        // columns..
    ]
});

// Phoneを最後に追加
var config = grid.getColumnModel().config;
config.push({id: 'phone', header: 'Phone', dataIndex: 'phone'});
grid.getColumnModel().setConfig(config, true);

ColumnModel#setConfig()を呼ばなくても、一見、追加できているように見えるがヘッダ行にカーソルをあわせた際にエラーが発生する。
また、GridPanelのコンフィグオプションで、以下のようにとしていると(両方共trueがデフォルト値)、追加後に列の配置が復元されるため、意図した位置に追加されないことがあるので配慮が必要。列の追加自体は特に問題ないのですが、ここで少しはまりました。。

enableColumnMove: true
stateful: true

JAX-RS (Jersey) でパラメータとして独自のクラスをインジェクトする (2)

このエントリの続きです。パラメータが多い場合には、対応するメソッドの引数が増えてしまうので、引数をDTOにまとめたいという話です。
例えば、id, foo, bar, bazという引数があるメッソッドで、これらの引数を以下のようなDTOにしてクエリパラメータやパスパラメータから値を自動で設定したいとします。

public class MyParams {
	@PathParam("id")
	public Integer id
	@QueryParam("foo")
	public String foo;
	@QueryParam("bar")
	public String bar;
	@QueryParam("baz")
	public Integer baz;
}

前回は、以下のようにResourceContextをインジェクトして、メソッド内でそれを介してMyParamsを取得していました。これだと、メッソッドの引数にResourceContextがあるのが少し気持ちがよくない気がします。今回はその続きで直接MyParamsをインジェクトします。

@Path("/myResource")
public class MyResource {
	@GET
	@Path("{id}")
	@Produces(//...)
	public String get(@Context ResourceContext rc){
		MyParams params = rc.getResource(MyParams.class);
		// ...
	} 
}

この方法は、JerseyのMLにある方法そのままです。まず、@ResourceParamという専用のアノテーションを作成します。

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResourceParam {
}

次に、このアノテーションが付加された引数をインジェクトするために、JerseyのInjectableProviderを実装したクラスを作成します。内部では、ResourceContextを使用した場合と同じことをやってます。

import java.lang.reflect.Type;
import javax.ws.rs.core.Context;
import com.sun.jersey.api.core.ResourceContext;
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;

public class ResourceParamInjector implements InjectableProvider<ResourceParam, Type> {
	private final ResourceContext rc;

    public ResourceParamInjector(@Context ResourceContext rc) {
        this.rc = rc;
    }

	@Override
	public ComponentScope getScope() {
        return ComponentScope.PerRequest;
	}

	@Override
	public Injectable getInjectable(ComponentContext ic, ResourceParam a, Type type) {
        if (type instanceof Class) {
            final Class c = (Class)type;

            return new Injectable() {
                public Object getValue() {
                    return rc.getResource(c);
                }
            };
        }
        return null;
	}
}

作成したResourceParamInjectorをApplicationクラスから登録します。

public class MyApplication extends Application {
	@Override
	public Set<Class<?>> getClasses() {
		Set<Class<?>> classes = new HashSet<Class<?>>();
		// ...
		//
		classes.add(ResourceParamInjector.class);
		return classes;
	}
}

以下のように使うことができます。

@Path("/myResource")
public class MyResource {
	@GET
	@Path("{id}")
	@Produces(//...)
	public String get(@ResourceParam MyParams param){
		// ...
	} 
}

何らかのオブジェクト自体ををPOST/PUTするようなケースは@ConsumesでJSONやXMLを処理すると思うので、あまり使わないかもしませんが。

JJUG CCC 2011 fall 行ってきた

すごい今更ですけど、10/17にJJUG CCC 2011 fall に行ってきました。基調講演の途中から参加しました。会場の国立オリンピック記念青少年総合センター初めて行ったので迷ってしまった。。

G-2 基調講演 JavaOne報告会 Part.2

JavaOne 2011 Report
View more presentations from Oracle Fusion Middleware

  • JavaでのGUI はswing から JavaFXがメインになる
  • Java SE8は2013年夏頃
  • 世界的にはJava EE6が最も使われている(ただしダウンロード数にGlassfishを含む)
  • Java EE6のWeb profileに対応したapache tomEEがリリースされた
  • Java EE7 -> クラウド対応(PaaS)
  • Glassfish4.0にはPaaSコンソールが付いている
  • EclipseLink2.3はマルチテナンシーをサポートしている。アノテーションで指定する。

Java on Heroku 河村嘉之

  • PaaSにおけるベンダーロックインは減ってきていて、オープンな技術が使われるようになってきた
  • Cedarというスタックで使えるようになった
  • Java on Heorku の環境は、ubuntu ,openJDK6
  • Play, Springのサポート
  • JavaEEのPaaSではないのでwarは使わない
  • Jettyなどのエンベデットのサーバーを起動する。
  • gitでpushしてディプロイ
  • Procfileというファイルにディプロイ時に実行するスクリプトを指定する。mavenでエンベデットのWebサーバを起動する。
  • PORTは環境変数から取得するようにする。
  • DBはPostgreSQL
  • gitを使うことでバージョン管理とディプロイをまとめてできるのは便利そう
  • GAEみたいに複数バージョンの管理はできるんだろうか
  • ライブコーディングでHello worldサーブレットがHeorkuで動かなくてログも出ていなかったのがちょっと心配
  • エンベデッドのサーバを起動するだけでよいのであれば、Glassfishを使えばEEでも普通に使えそう

B-2 Node.js ― Hello, world! の1歩先へ。

  • DBへのアクセスも非同期処理で書く
  • Webアプリケーションを書くのであれば、Expressというフレームワークを使う

Node.jsには関係ないけど、発表者の方がライブコーディングでWebStormを使ってた。私も試してみよう。

B-3 Jenkinsによるpre-tested commit

  • Jenkins のフォーク後の新規のチケットやコミット数の統計ではJenkinsが活発
  • 今後はLong-Term Support release(LTS)も提供していく
  • もったいないので開発者のPCをテストに使わない
  • Jenkinsが回帰テストしてOkだったらリポジトリにマージするイメージ
  • gerritというコードレビューツールををつかう方法
  • gitで個人用ブランチやフィーチャーブランチを作成し、そこをJenkinsが監視してテスト→マージ
  • テストしてからマージすると、マージ後に問題が発生する可能性がある
  • Subversionの場合には、Subversion Merge Pluginプラグインがある。
  • Jenkins用のブランチを作成してそこにコミットするとJenkinsがテストしてくれる。マージやrebaseもワンクリック。
  • Mercurial用はないからGitのを参考に作って。
  • Jenkinsの開発にはGerritを使っているが、今はうまく回っていない。

Designing pre-tested commit - hudson - Hudson Wiki

C-4 楽々Scalaプログラミング 浅海智晴 (日本Javaユーザグループ 副会長)


Scalaなどの関数型プログラミングでのデータの操作は、XSLTでのXMLの操作に例えていたのがしっくりきた(正しいのかはScala勉強中なのでわからないけど)。

Google Developer Day 2011に行ってきた

もう一週間近く経ってしまいましたが、11/1にGoogle Developer Day 2011 Japanに行ってきました。

セッションのメモ

個人的に気になった部分だけのメモですが。

  • Android の優れたユーザーエクスペリエンス
    • fast
      • UIスレッドで時間がかかる処理をしない。Strict Mode使うと検出しやすい。
      • Javaのconcurrentパッケージ使ってもいいけど、AsyncTask, IntentService, Loader(v11〜)使って。
      • TraceViewで計測して。
      • 0.2秒以上かかりそうならプログレスバー出して。
    • usable
      • ActionBar
      • MultiPaneレイアウト
      • App Navigation(back / up)
    • beautiful
      • 開発者がデザインを勉強するのもよいが、もっとデザイナーと協力して良いデザインのアプリを。
    • listen to your users
    • widget styling and theme
      • 共通の標準テーマ: holo
      • 端末毎の標準テーマ: device default
    • 3.0+
      • xhdpi
      • ハードウェアのメニューボタンがない端末を想定して
      • sw600dp
    • ActionBar
    • android-ui-utils - Android UI Utilities使って。
  • 今までにないサイトを作る:HTML5 による最新ウェブアプリ
  • Google Apps : 新しい API、新機能、ベストプラクティス
    • GData APIが使いにくいのでREST+JSONベースで作り直してる
    • Google APIs Explorer使ってみて
    • GoogleApps scriptのDocumentAppを使ってGoogleDocsの文書をテンプレートにPDFを作ってメールで送ったりできる
    • Google Picker APIPicasaなどのデータを簡単に選択できる
    • Google Apps Marketplaceで流通
    • 管理者以外もアプリをインストールできるオプションができた
    • Appsのユーザーの間でのアプリのおすすめができる機能がある
  • VC パネル: 起業家精神、起業支援とベンチャーキャピタル
    • マーケットが小さい国のベンチャーは当初からシリコンバレーを意識している。日本はある種のぬるま湯状態。
    • 日本のベンチャーは下請け開発なので疲弊してしまう
    • シリコンバレーは文化がないので成功したベンチャーはサンフランシスコに移る
    • 日本は開発者とデザイナが分断されている傾向が強い
    • できるだけ早く失敗すべき。
    • 妻(夫)や子供ができるまえにチャレンジすべき。

全体的にGoogleのサービスに関するセッションがメインで、去年はあったGWTとかClosure Libraryとかのツール的なプロダクトの話はほぼなしでしたね。ChromeのDeveloper Toolsについてのセッションはありましたが私はAndroidのセッションを聴いてました。基調講演で紹介された難読化されたJSを再整形する機能はよさそうでした。
個人的にはもうちょっと細かいGoogleでのアプリケーションの開発方法なんかを聞きたいと思うのですが。

感想など

Androidアプリの開発もAppsScriptももっと本格的にやりたいですね。Andoridの方は2年前からそう思っていて、いまだ嗜む程度なので、、ダメダメですが。
あとは、プログラミングの技術も重要だけど、これからはもっとデザインを意識したいというか、もっとデザイン力を付けたいなと思いました。ちょうどGoogleのサービス・アプリがデザインを一新したり、hatenaブログがデザインをウリの一つにしていたりするタイミングですし。特に業務系のアプリケーションなんかを作っているとデザイン二の次になりがちで、私もextjsとかjqueryUIとかそのままでデザインもそこそこになるライブラリに頼っています。プログラミングと違ってどうやって身につけるかは難しいですが。
会場が去年の東京国際フォーラムからパシフィコ横浜に戻ったのはよかったです。国際フォーラムの方が近いのですが、去年はセッション会場間の移動に時間がかかったりお弁当の配布が混乱していたりとあまり良い印象がなかったので。
あと今年のTシャツは素材がかわって、肌触りとフィット感がよいですね。遅れていったのでSサイズしか残っておらず、ちょっとピチピチなですが、こういうイベントのTシャツはアメリカンサイズでダボッとしがちなのでかえっていい感じです。