GWT2.5でソースマップを使ってデバッグする

 前回のエントリーでSuper Dev Mode(以下SDM)の実行の仕方を書きましたが、SDMで開発する際のデバッグの方法としてソースマップを使うことができます。

ソースマップとは?

 ソースマップとは最終的にJavaScriptコンパイルして使う言語(CoffeScript、TypeScript等)をブラウザ上でデバッグしやすくする技術で、サーバー側にてCoffeeScript等の言語と実際のJavaScriptの紐付け情報をJSON形式でブラウザにダウンロードさせて、ブラウザ側でCoffeeScriptやTypeScript等のソースにブレークポイントをはってデバッグ出来るようにする技術です。通常、JavaScriptコンパイルする言語はブラウザ側にてJavaScriptデバッグしたとしても元々のコンパイル前のソースとは違う形になっているためデバッグがしづらいと言った問題がありましたが、この技術を使うことでデバッグがかなり楽になります。そしてGWT2.5からはGWTでもソースマップを使用して開発ができるようになっています。

GWTでのソースマップ

 やり方は簡単で、SDMにてGWTアプリケーションを実行し、Chromeの開発コンソールを開きます。その後、開発コンソール上の右下にある設定ボタンをクリックし「Enable Source Maps」にチェックを入れ、画面の再ロードを行います。これによりソースマップが有効になります。あとは「Sources」タブを開けばJavaファイルの参照も行えるようになり、そのJavaファイルにてブレークポイントの設定などが出きるようになります。

GWT2.5.0でのソースマップ

 上記でGWT2.5でもソースマップを使えると書きましたが、実際はバグにより2.5.0では使えず、2.5.1から使えるようになります*1。ただし、ちょっとした裏技で一応使えるようになります。以下はその手順です。

ソースのコピー

 まず、自分のGWTアプリケーションのソースディレクトリ内にcom.google.gwt.core.linkerというパッケージを作成します。その後、com.google.gwt.core.linker.CrossSiteIframeLinkerのソースをコピーして先ほど作成したパッケージにペーストします。

ソースの修正

 先ほど作成したCrossSiteIframeLinkerの407行目の「out.print("\n//@ sourceURL=0.js\n");」をコメントアウトします。Mavenを使用している場合はgwt-dev-2.5.0を依存関係に追加してください。


以上で2.5.0でもソースマップを使うことが出きるようになります。ただし、無理やり感が否めないため何か副作用が発生する可能性は高いのでその点は注意が必要かと。

*1:2月3日時点ではまだリリースされていませんがこの数週間でリリースされると思います。

GWTをSuper Dev Mode で動かす(Maven)

GWT2.5からSuper Dev Modeという機能が追加されています。
この機能を使って開発すると、2.4までの開発モードに比べてクライアント(ブラウザ上)での動作が早くなることや、開発するためにブラウザにGWTプラグインを追加する必要がなかったります。ただ、欠点としてはソースコードの修正等をリアルタイムに反映させることは出来ず、自分で明示的にコンパイルさせなければいけません。

使い方

プロジェクトの作成

サンプルとしてmavenプロジェクトを作成します。

mvn archetype:generate -DarchetypeRepository=repo1.maven.org -DarchetypeGroupId=org.codehaus.mojo -DarchetypeArtifactId=gwt-maven-plugin -DarchetypeVersion=2.5.0

対話形式でgroup idやmodule名等を入力するとgwtの雛形プロジェクトが作成されます。

gwt.xmlへの追記

次に上記で入力したmodule名と同名のgwt.xmlファイル(上記のmodule名にてHogeと入力していればHoge.gwt.xml)に下記の内容を追加します。

<add-linker name="xsiframe" />
<set-configuration-property name="devModeRedirectEnabled" value="true" />
code serverの起動

次はcode serverを起動します。

mvn generate-sources gwt:run-codeserver
プロジェクトの実行

そして、上記code serverを起動している状態でプロジェクトの実行を行います。

mvn gwt:run
code serverへのアクセス
http://localhost:9876/

上記アドレスにアクセスし「Dev Mode on」のボタンのリンクをブラウザのブックマークに追加します。

Super Dev Modeでコンパイル

http://localhost:8888/Hoge.htmlにアクセスし、上記で追加したブックマークをクリックして「Compile」をクリックします。

これでSuper Dev Modeでの開発が可能となります。最初に述べたようにEclipseなどのIDEでソースを修正した後はブックマークをクリックし「Compile」を押さないと修正が反映されませんが、以前の開発モードだとリアルタイムで修正が反映される反面ブラウザの更新まで多くの時間を要していた部分が短縮されるので結果Super Dev Modeの方が開発スピードは上がると思われます。


Vaadin - その1

VaadinというJavaフレームワークを調べてるのでメモ。
VaadinとはGWTをベースとし、WebアプリケーションにてリッチなUIを表現するのに長けたJavaフレームワークです。
ちょっと触った感じだとSwting的にコードが書けて、JavaScriptとHTMLを書かずにリッチなUIを表現することが可能なので結構面白いかなと。

現在の安定版は6.8.4ですがアーキテクチャとかいろいろ変更がある予定の7系(現時点ではbeta6)でとりあえずプロジェクトの雛形を作ってみます。
ちなみにVaadin7からはJava6が必須となっています。

mavenで雛形を作るのが楽なので下記mavenのコマンドを実行します。

mvn archetype:generate -DarchetypeGroupId=com.vaadin -DarchetypeArtifactId=vaadin-archetype-application -DarchetypeVersion=7.0.0.beta6

実行するとgroupIdとかartifactId等の入力を求められるので任意の文字列を入力すれば雛形の出来上がりです。
上記コマンドで作成されたプロジェクトディレクトリに移動して

mvn package
mvn jetty:run

を実行すると組込みのjettyが起動するのでlocalhost:8080にアクセスすればOK。

とりあえず今日はここまで。

Wicket1.5での変更点 - その1

WicketではDEPLOYMENTモードとDEVELOPMENTモードというのがありますが*1、1.5からはその指定の方法が変わってます。このモードの指定方法はいくつかあって、システムプロティーに設定する方法、web.xmlに指定する方法、ソースコード上にて指定する方法などがあります。この内ソースコード上にて指定する方法が1.5から変更されています。変更内容は単純で、文字列を返してたところをenumで返すようになったというだけです。web.xmlシステムプロティーでの設定方法は変わりません。

1.4系の場合、DEPLOYMENTモードにするにはWebApplicationクラスを拡張したクラス内で下記のようにしていました。

public class MyApplication extends WebApplication{
    @Override
    public String getConfigurationType(){
        return Application.DEPLOYMENT;
    }
}

これが1.5からだと下記のようになります。

public class MyApplication extends WebApplication{
    @Override
    public RuntimeConfigurationType getConfigurationType() {
        return RuntimeConfigurationType.DEPLOYMENT;
    }
}

まぁ、あんまりソースコード上でこの設定をする人はいないかもしれませんがw

*1:DEVELOPMENTモードだとAjaxのデバックコンソールとかwicket:idが表示される。ちなみにデフォルトはDEVELOPMENTモード

RuleChainを使ったJUnit4.10以降の拡張方法

JUnit4.10が先月リリースされましたが、このバージョンでもいくつか機能追加がされています。今回はそのうちの1つのRuleChainの使い方について。

RuleChainというクラスを使うと複数あるRuleを名前のとおりChainさせて使うことが可能になります。

以前書いたエントリーでは特定のアノテーションがあったらゴニョる感じにしてたので、それを流用する感じでサンプルを作成してみます。

まずは独自のアノテーションを2つ用意します。

@Retention(RetentionPolicy.RUNTIME)
public @interface FooAnnotation {  
}
@Retention(RetentionPolicy.RUNTIME)
public @interface HogeAnnotation {
}

んで、上記のアノテーションがあった場合に独自の処理を行うTestRuleのサブクラスをそれぞれ作成します。

/**
 * Fooアノテーションがあったらゴニョる。
 */
public class FooRule implements TestRule{

    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                if (isAssign(description))
                    System.out.println("Foo処理開始。");
                base.evaluate();
                if (isAssign(description))
                    System.out.println("Foo処理終了。");
            }
        };
    }

    private boolean isAssign(Description description) {
        return description.getAnnotation(FooAnnotation.class) != null;
    }
}
/**
 * Hogeアノテーションがあったらゴニョる。
 */
public class HogeRule implements TestRule{
    
    @Override
    public Statement apply(final Statement base,final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                if (isAssign(description))
                    System.out.println("Hoge処理開始。");
                base.evaluate();
                if (isAssign(description))
                    System.out.println("Hoge処理終了。");
            }
        };
    }
    
    private boolean isAssign(Description description){
        return description.getAnnotation(HogeAnnotation.class) != null;
    }
}

そして、上記をつかってテストクラスを下記のように作成します。

public class RuleChainSampleTest {

    //ここで2つのRuleを使ってChainさせる
    @Rule
    public TestRule chain = RuleChain.outerRule(new FooRule()).around(new HogeRule());
    
    @HogeAnnotation
    @FooAnnotation
    @Test
    public void test1() throws Exception {
        System.out.println("test1");
    }
}

上記を実行した場合に出力されるコンソールは下記になります。

Foo処理開始。
Hoge処理開始。
test1
Hoge処理終了。
Foo処理終了。

RuleChain.outerRuleにて指定するのが一番外枠になって、そこからaroundでつなげていく感じです。Decoratorパターンに近い感じでしょうか。
いままでだとそれぞれの機能をもった1つのRuleを作成したり、Ruleを使わない場合はRunnerを拡張したりしてましたがそれをする必要がなくなっていて、良い感じで拡張できるようになっています。

自分はDBアクセスが絡むテストとかはアノテーションを作成していろいろ拡張して使うのですが、このRuleChainを使うと今まで作ってたようなJUnitの拡張がより簡単になるイメージですねぇ。

でも、publicフィールドっていうのが(ry

TestRuleを使ったJUnit4.9以降の拡張方法 - ClassRule

いつの間にかリリースされてたんでせっかくだからエントリー書こうと思って途中までいろいろ書いてたけど調べたら既に綺麗にまとめられたブログを見つけたのでトラックバックするだけで今日のエントリーは終了w*1

http://d.hatena.ne.jp/backpaper0/20110920/1316534832

@BeforeClassや@AfterClassを使用する場合に比べると、より共通化がしやすいのが@ClassRuleって感じですかねぇ。
明日はJUnit4.10から機能追加されたRuleChainについて書こうかと思いますです。

*1:ついでに前回のエントリーもちょっと加筆しておきました

Wicket1.5 をJavaEE6環境で動かす!

Wicket1.5はすでにリリースされているのですが、JavaEE6(正確にはServlet3.0)で導入された機能にはまだデフォルトでは対応していません。*1
しかしWicket1.5を使っている人の中には「web.xmlなんか書きたくねー!」とか「どうせやるなら最新のJavaEE環境でしょ」と言う人ももしかしたらいるかもしれない。そんな人にうってつけなのがWicket-stuffの1モジュールであるwicket-servlet3です。こいつを使えばweb.xmlなしで快適なWicket生活を送れること間違いなし!

ということで使い方です(maven前提)

まずはpom.xmlwicket-stuffのrepositoryの追加をします。

    <repositories>
        <repository>
            <id>wicketstuff-core-releases</id>
            <url>https://oss.sonatype.org/content/repositories/releases</url>
            <releases>
                <enabled>true</enabled>
            </releases>		
        </repository>	
    </repositories>

次に依存関係の追加。

    <dependencies>
	<!--  WICKET DEPENDENCIES -->
        <dependency>
            <groupId>org.apache.wicket</groupId>
            <artifactId>wicket-core</artifactId>
            <version>1.5.2</version>
        </dependency>
        
        <!-- こっからがwicket-stuffの設定 -->
        <dependency>
            <groupId>org.wicketstuff</groupId>    
            <artifactId>wicket-servlet3</artifactId>
            <version>1.5-RC5.1</version>
            <!-- 依存モジュール(wicket-core等)のバージョンに差異がでるのでexclude -->
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>wicket-core</artifactId>
                    <groupId>org.apache.wicket</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>servlet-api</artifactId>
                    <groupId>org.mortbay.jetty</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>wicket</artifactId>
                    <groupId>org.apache.wicket</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    <dependencies>

やることはwicket-servlet3の依存関係を追加してやることだけなのですが、残念ながらこのモジュールはまだバージョンが1.5-RC5.1です。なので当然依存するwicket-coreのバージョンも1.5-RC5.1です。なので一応exclusion設定をしておきます。

んで、今度は独自Filterの作成です。
継承元はwicket-servlet3のWicketFilter3というクラスです。
んで、Servlet3.0の仕様に沿ってアノテーション付けたりとかそこらへんをやります。(指定するパラメータはweb.xmlに書いてるのと同じ)

@WebFilter(value="/*",initParams={@WebInitParam(name="applicationClassName",
                          value="com.mycompany.wicketjavaee6.MyWebApplication")})
public class MyFilter extends WicketFilter3{
}

以上です。あとはWicketのPageクラスつくったりWebApplicationクラスのサブクラスを作ったりといういつもの流れでコーディングした後にGlassfishなりtomcatなりのServlet3.0対応コンテナにデプロイすればOKです。

「web.xmlが減った代わりにFilterクラスが増えただけで、別になにも便利になってなくね??」という想いは心にしまって、JavaEE6環境でWicketアプリを動かしてるという優越感にしばし浸るのが健康的かと思います。

*1:例えばアノテーションによってweb.xmlを定義しなくていいとか