DeltaSpikeのProjectStageと@Exclude

DeltaSpike-0.1がリリースされたので早速利用してみました。とりあえずドキュメントにもあるProjectStageと@Excludeアノテーションを利用した簡単なサンプルを紹介します。

そのまえに、個人的なメモというか、とりあえず調べ始めたばかりなので、情報の正確さはいっさい保証しないのでそのへんよろしく。

Mavenを利用するのが手っ取り早いのでサイトのドキュメントに従って設定してみたら早くもエラーが。versionを"0.1-incubating"と設定しないとだめみたいです。Mavenの依存関係を解決し、気を取り直して次に進むことに。

DeltaSpikeではJSF2同様にProjectStageという概念がありますが、JSFのProjectStageよりも多くのStageをサポートしています。(Stagingとかいろいろ。詳細はドキュメントを参照)基本的にはJSFのProjectStageと同様の機能を提供するようです。

で、@Excludeというアノテーションですがこれは、CDI管理Beanの中で、除外したいクラスに付与します。

@Exclude
public class ExcludedBean {
    ...
}

この@Ecludeアノテーションですが、ProjectStageとあわせて動作させることが可能となっており、例えば特定のProjectStageによってDIするクラスを変えることも可能なようです。今回は、現在のProjectStageを返すBeanをサンプルで簡単に紹介します。

まず、Stageというインターフェースを用意し、現在のステージを返すメソッドを定義します。

public interface Stage {

    public String getStage();
}

次にこのインターフェースを実装した、DevelopmentStageとProductionStageというクラスをそれぞれ作成します。

import javax.inject.Named;

import org.apache.deltaspike.core.api.exclude.Exclude;
import org.apache.deltaspike.core.api.projectstage.ProjectStage;

@Named("stage")
@Exclude(exceptIfProjectStage = ProjectStage.Production.class)
public class ProductionStage implements Stage {

    @Override
    public String getStage() {
        return "Production stage.";
    }

}
import javax.inject.Named;

import org.apache.deltaspike.core.api.exclude.Exclude;
import org.apache.deltaspike.core.api.projectstage.ProjectStage;

@Named("stage")
@Exclude(exceptIfProjectStage = ProjectStage.Development.class)
public class DevelopmentStage implements Stage {

    @Override
    public String getStage() {
        return "Development stage.";
    }

}

この2つのBeanには@Namedで同じ名前が定義されています。通常ではBeanの識別が不可能ですが、@Excludeアノテーションで、それぞれProductionStageクラスであればProjectStageがProduction、DevelopmentStageクラスであればDevelopmentでなければ除外します。@ExcludeのexceptIfProjectStageがまさにそれを定義している部分で、これはBeanが指定したステージと異なっている場合は除外するという意味になるようです。

@Excludeアノテーションはこれ以外にもいろいろな指定ができるようです。(詳細はドキュメント参照)

では、このBeanをDIし利用するクラスを定義します。

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@RequestScoped
@Named
public class StageConfirmation {

    @Inject
    private Stage stage;
    
    private String currentStage = "";
    
    public String confirm() {
        this.currentStage = stage.getStage();
        return "confirm";
    }

    public Stage getStage() {
        return stage;
    }

    public void setStage(Stage stage) {
        this.stage = stage;
    }

    public String getCurrentStage() {
        return currentStage;
    }

    public void setCurrentStage(String currentStage) {
        this.currentStage = currentStage;
    }
}

このBeanにDIされるクラスは現在のProjectStageによって変更することが可能なようです。

結果を表示するViewを用意しAPサーバにデプロイして結果を確認してみてください。

【確認用のView】

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">

    <h:head>
        <title>Current stage confirmation.</title>
    </h:head>
    <h:body>
        Now, It's #{stageConfirmation.currentStage}         
    </h:body>
</html>

とりあえず自分の環境では以下のように表示されました。


Now, It's Production stage.

特に何もしないと、Productionのようですね。ProjectStageをDevelopmentにかえるとどうなるかというと、、、変え方がよくわかりません。「ProjectStageによって変更することが可能なようです。」と表現したのは始めたばかりでまだよくわかってないからです。ただ、ドキュメントを読む限りでは理論的に可能のようです。SeamFacesでも確か似たような機能があったからその延長のような気がします。

で、DeltaSpikeのProjectStageクラスのJavadocコメントを見てみると、現在のProjectStageを決定するメカニズムに関するコメントがTODOになっているみたいです。うーん、どうやら、現時点では現在のProjectStageを決定する仕組み自体がほんとにないのかもしれません。

まあ、まだversion-0.1なので、いろいろ変わると思いますが、少しずつ調査していきたいと思います。