Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

CDIのStereotypes

仕事でいつから使えるようになるのかわからないJava EE 7ですが、Java EE 7 Essentialsをコツコツと読んでいます。

Java EE 7 Essentials
Java EE 7 Essentials
posted with amazlet at 14.08.11
O'Reilly Media (2013-08-14)

で、CDIの所でStereotypesなるものが出てきました。個人的にはあまり聞きなれず。

ぐぐってみたら、きしださんの以下エントリで@Stereotypeでアノテーションがサラっと触れられてました。

きしだのはてな Java EEのCDIで定義しておくと便利なプロデューサーとインターセプター

まとめる、ってなんだろう?と思って触ってみたら、ホントにCDIのアノテーションをまとめる機能でした(^^;

例えばCDI管理Beanでこんな定義があったとして

@Named
@RequestScoped
@Transactional
public class IndexBean implements Serializable{
    //定義
}

まぁ割と普通なのですが、これが以下のように書けたりします。

@MyStereotype
public class IndexBean implements Serializable{
    //定義
}

で、別途以下の修飾子を定義し、ここで使うアノテーションをまとめておく形です。

@Stereotype
@Named
@Transactional
@ViewScoped
@Retention(RUNTIME)
@Target(TYPE)
public @interface MyStereotype {
}

ってか、別にJava EE 7関係なく、Java EE 6でもあったんですね(^^;
Tutorialがひっかかりました。
http://docs.oracle.com/javaee/6/tutorial/doc/gkhqc.html

Alcでstereotypeを調べると色々意味がありますが「過度に単純化した概念」辺りがピタッと来る感じです。
http://eow.alc.co.jp/search?q=stereotype

Java EEのDIを可視化するVisual EE

Mavenでビルドするだけで以下動画のようなCDIを可視化するHTMLを出力してくれます。

少し前にAdam Bienさんのブログにて

VISUALIZE YOUR JAVA EE 7 DEPENDENCY INJECTION AND RELATIONS

と紹介されていたものです。Visual EEは以下に。

Visual EE

使い方は簡単で、mavenのpom.xmlに

<plugins>
    <plugin>
        <groupId>de.struller-baumann</groupId>
        <artifactId>visualee</artifactId>
        <version>0.26</version>
        <configuration>
            <outputdirectory>visualee</outputdirectory>
        </configuration>
        <executions>
            <execution>
                 <phase>process-resources</phase>
                 <goals>
                     <goal>visualize</goal>
                 </goals>
            </execution>
         </executions>
    </plugin>
</plugins>

と設定するだけ(^^;コードにCDIを利用したものが入っていればビルドした結果、srcと同列階層にvisualeeというフォルダができます。

コードは@Injectがあるだけでも先ほどのような表示がされます。

@Named
@ViewScoped
public class CdiBean {

    @Inject
    private SimpleDependent dep;
}
@Dependent
public class SimpleDependent {
    
}

f:id:kikutaro777:20140707193532j:plain

@Producesもちゃんと描いてくれます。

@Dependent
public class SimpleProducer {
    @Produces
    @SimpleListQualifier
    public List<String> getSimpleStrList(){
        return new ArrayList<>();
    }
}

f:id:kikutaro777:20140707193209j:plain

残念ながら@Alternativeを利用した場合の実体インスタンスのInjectまでは描いてくれませんでした(^^;
インタフェースがInjectされた絵となってます。

f:id:kikutaro777:20140707193848j:plain

SimpleImplDependentOneとSimpleImplDependentTwoが@Alternativeついた実装クラスですがプカプカ浮いてます。このツールが出力するhtml(というかグラフ描いてるjs)のほうが興味深いですね

CDIによるデコレータ

先日書いた「プリミティブ型もCDIでInject」に続いて、今回もCDIの中で知らなかったネタなのですが。

CDIの仕様の中で、@Decoratorを利用してGoFのデザインパターンにあるデコレータパターンを記述する方法があるとのこと。

デコレータパターンについては

辺りがわかりやすいかと。

簡単に書いてみたら、あっさり動きました。

こんなインタフェースを用意して

package jp.co.hoge.decorator;

public interface HogeExecutor {
    public void execute();
}

標準出力で「hogehoge」と出すだけの実装クラスを定義します

package jp.co.hoge.decorator;

public class HogehogeExecutor implements HogeExecutor{

    @Override
    public void execute() {
        System.out.println("hogehoge");
    }
}

これをデコレーションしてみます。@Decoratorというアノテーションをつけたクラスを用意して、@DelegateをつけたHogeExecutorをInjectして、その周辺をデコるだけ。

package jp.co.hoge.decorator;

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;

@Decorator
public class HogehogeDecorator implements HogeExecutor{
    
    @Inject
    @Delegate
    private HogeExecutor hoge;

    @Override
    public void execute() {
        System.out.println("でこれーしょん");
        hoge.execute();
        System.out.println("でこでこ");
    }   
}

このクラスをbeans.xmlに以下のように定義してあげれば

<decorators>
    <class>jp.co.hoge.decorator.HogehogeDecorator</class>
</decorators>

とある管理対象Beanとかで

@Inject
private HogehogeExecutor hogehogeExec;
    
@PostConstruct
public void init(){
    hogehogeExec.execute();
}

とかすると標準出力で

でこれーしょん
hogehoge
でこでこ

のように表示されてデコレーションされました。意外と簡単ですね。
クラスの機能拡張=継承、と条件反射的になりがちだけど、こういう道もあるなーと改めて。

プリミティブ型もCDIでInject

悲しいことに最近仕事でコードが書けなくなってきてしまい(苦手な上流へ…)、あまりネタがないのですが、プライベートな時間で以下のJava EE7本を細かく読み始めました。

Beginning Java EE 7 (Expert Voice in Java)
Antonio Goncalves
Apress (2013-06-26)
売り上げランキング: 4,378

このBeginning Java EE 7は名前からわかる方もいると思いますが、金魚本のJava EE 7版となっていて、先頭の章でCDIがドカンと入ってていい感じです。

しかし本を読んでいると、CDIは細かい所で結構知らないことあるなぁと。

そんなわけで個人的なメモ。

プリミティブ型やStringもCDIのProducersを利用してInjectできるんですね。へー。
地味に知らなかった(^^;

package jp.co.hoge.producer;

import javax.enterprise.inject.Produces;

public class NumberProducer {
    @Produces
    @MyNumber
    public int myNumber(){
        return 11;
    }
}
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface MyNumber {
}
@Inject
@MyNumber
private int number;
System.out.println("私の堀北真希さんファンクラブ会員番号は" + number);

私の堀北真希さんファンクラブ会員番号は11

とか

package jp.co.hoge.producer;

import javax.enterprise.inject.Produces;

public class HorikitaProducer {
    @Produces
    @Makimaki
    public String getHorikitaName(){
        return "堀北真希";
    }
}
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Makimaki {
}
@Inject
@Makimaki
private String name;
System.out.println(name);

堀北真希

みたいな。メリットはなんだろ…。

Injectで起きた循環依存(circular dependencies)

一緒に開発している後輩から「こんなエラーが」と見せてもらったら

org.jboss.weld.exceptions.DeploymentException: WELD-001443 Pseudo scoped bean has circular dependencies. Dependency path [Session bean [class jp.co.hogehoge.ejb.OpportunityLogic with qualifiers [@Any @Default]; local interfaces are [OpportunityLogic], Session bean [class jp.co.hogehoge.ejb.CustomerLogic with qualifiers [@Any @Default]; local interfaces are [CustomerLogic], Session bean [class jp.co.hogehoge.ejb.OpportunityLogic with qualifiers [@Any @Default]; local interfaces are [OpportunityLogic]]

と出てました。話を聞いてみると、あれ、これ今までよくなかったな…とも思ったり(^^;
(環境はJava EE6,GlassFish3.1.2.2)

すごいざっくりした例にすると以下のようなコードです。

例えば商談情報に関する処理をするEJBと顧客情報に関する処理をするEJBがあって、以下のように互いでInjectしてしまったような場合です。(実際以下お試しコードで出たエラーが上記)

package jp.co.hogehoge.ejb;

import javax.ejb.Stateless;
import javax.inject.Inject;

@Stateless
public class CustomerLogic {

    @Inject
    private OpportunityLogic oppLogic;
    
    public String findCustomer(){
        //本来DBから顧客データを取得するような処理とか
        return "顧客情報だよ";
    }
}
package jp.co.hogehoge.ejb;

import javax.ejb.Stateless;
import javax.inject.Inject;

@Stateless
public class OpportunityLogic {

    @Inject
    private CustomerLogic customerLogic;
    
    public String findOpportunity(){
        //本来DBから商談データを取得するような処理とか
        return "商談情報だよ";
    }
}

商談の処理の中で顧客情報を取ったり、顧客の処理の中で商談情報を取ったり、わりとありがちな…(^^;

「circular dependencies」でググったら英語でたくさん情報出てきたので、結構ある話なんだなぁと。

というか、javax.inject.InjectクラスのJavaDocにも説明があった(^^;
http://docs.oracle.com/javaee/6/api/javax/inject/Inject.html

対策としては以下StackOverflowで

CDI injection loop
http://stackoverflow.com/questions/15300338/cdi-injection-loop

  • 1つのクラスにしてしまう
  • もう1つ別のクラスを作って、各々それをInjectする

という感じに書いてありました。スコープ変えてもいけるよ的な情報もありましたが、イマイチよくわからず…(^^;

JJUG ナイトセミナ 「Java EE 特集」に参加しました~

今日のJJUGナイトセミナは「Java EE特集」でした。最終的な参加者は170名超えだったとのことで、あれ、結構Java EE盛り上がってきてる…?のかと思ったり(^^;
http://www.java-users.jp/?p=846

発表は2つだったのですが、どちらもかなり勉強になりました。まだまだ知らないことあるなぁと。

というわけで、資料が公開されることを期待しつつ、感想などを。
(資料は既に公開されてました!)

CDIをはじめよう @n_agetsuさん

CDIは金魚本に少ししか載ってなくて、自分も前回の開発ではネットを中心に、そして英語情報中心な感じで使ってました。

今日の話をもっと前に聞いていれば…(*´Д`)と思ったり。

そもそもDI(Dependency Injection)とは…的な話から丁寧に説明があって、改めてふむふむ、と。

インジェクションされる側の条件とか生成される側の条件とか、インジェクションできる対象が複数ある場合の挙動(デプロイ失敗)とか、こういう細かい所って、わりとなんとなく…な感じで使ってたなぁ、と今日の話を聞きながら反省(^^;

Java EE6と7での話やCDIEJBの機能比較・使い分けなどなど、この資料めっちゃ欲しいです!という感じです!是非
と書いてたら早速資料を上げて下さってました!!!

あと個人的にびっくりだったのは、Arqullianキーワードが意外とホットな感じだったことw
あれ、みんな普通に使ってる…!?みたいな。もっともっと日本語情報増えると嬉しい感じですね(^^)

しかし、前に聞いた@den2snさんのJSFや@n_agetsuさんが前に発表されていたjBatch、そして今回のCDIを聞いて、こうしたテーマで全体を綺麗に整理して色々説明できるってすごいなぁ、と改めて思いました。自分の場合は、開発で時間に追われる面もあって(言い訳…)、使う所だけを食ってる感じなので…。

CDIに関してはブログでも記述されてるとのことで、以下記事も要チェックです。
Java EE環境におけるCDIのデフォルト化

おっぴろげ JavaEE DevOps @nagaseyasuhitoさん

今日の会場でもあったグリーの永瀬さんからの話でした。

Java EE7も出て、Java EEいいね、いいね、と聞くけど、実績の話あまり聞かなくないですか?本当に使われてるんですか?的なスタートw

ちょうど今日関連する記事が出てましたね~と、永瀬さんが発表の中で自分のインタビュー記事を紹介して下さり、恐縮でした(^^;
(たまたまなのですが、少し前に自分のJava EE6開発に関してOracleさんにインタビューして頂いた記事の公開が今日でした→初めてのJava EE 6開発! 最初の壁をどう乗り越えた?──最新Java EE開発“虎の穴” 第1回)

そんな流れの中、グリーさんでの初Java EEの実績話、でした。

ってか、グリーさんがJava EE!?とかちょっと思いましたが、流れ的にはScalaで話が上がったのち、かくかくしかじかでJava EEになったとのこと。構成としては、JAX-RSCDIJPAがメインでJMSなども利用しているそうです。

コード例も豊富だったのでこちらも是非資料が欲しい…(>_<)と書いてたら、もうあがってました(^^;
発表資料もすごく綺麗で、コード例も使ってる技術の部分が色付けされてて、読み手に優しい感じでした。

聞いてて自分の勉強が足りないなーと思ったのはGlassFishのasadminコマンドやmavenのプラグインの使いこなし度(ってか他も色々なんですが)。そんなのあるのかーという発見が(^^;

あとはサービス止めずにGlassFishのデプロイモジュール差し替えとかは、まさに運用ノウハウな感じですごかったです。監視系も。この辺、今の自分達が弱すぎる面なので勉強していきたい。

Arqullianも利用されていたり、JenkinsによるCIや自動デプロイも行ってるとのことで、色々共通点あるなぁと思いつつ、ユニットテストとインテグレーションテストの間にソースいじられてコミットされたケースとかまで想定されていて全体的にレベルがすごい(^^;そこまで考えたことなかった。。

と、そんなこんなで、どちらもすごく勉強になりつつ、良い刺激になりました。

JSF2.2ではCDI管理対象BeanでViewScopedが使えるっぽい!!

間違ってたら指摘下さい(^^;

Java EE7が出てLive Webcastをみたとき、CDIで増えたスコープは

  • TransactionalScoped
  • FlowScoped

と紹介されていて、なんでViewScopedは入らないんだろう…と不思議でした。

自分がJava EE 6を勉強し始めて、管理対象Bean(BackingBean)をどう作るか、具体的には、JSF管理対象を使うか、CDI管理対象を使うか悩んでいたとき(CDI管理対象にすれば色々楽できそうだから使いたいけど、JSFのViewScopedがすごく欲しい、という感じだった…)、以下のサイトがとても有益でした。

で、上記ページ内でも書かれているように、CDIの標準でViewScopedはないため、どうしても欲しい場合は独自に定義するなどが必要でした。

で、今回もないのかーと思っていたら以下のサイトを見つけ

でもこの記事古いんだ…と思いつつ、NetBeans7.3.1を立ち上げて書いてみたら、なんか2つ出てきた!
f:id:kikutaro777:20130623010223j:plain

試しに以下書いてみました。

import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.faces.view.ViewScoped;

/**
 *
 * @author kikutaro777
 */
@Named(value = "confirmScopeBean")
@ViewScoped
//@RequestScoped
public class ConfirmScopeBean implements Serializable{

    private int count;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
    
    public void countUp(){
        count++;
    }

    public ConfirmScopeBean() {
    }
}

ビューは

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:outputLabel value="#{confirmScopeBean.count}" />
            <h:commandButton value="カウント" action="#{confirmScopeBean.countUp()}" />
        </h:form>
    </h:body>
</html>

ちなみにRequestScopedだとボタンを押して1度カウントされるだけの繰り返しです。
(1回のリクエストごとに消えるから)
f:id:kikutaro777:20130623010551j:plain

で、ViewScopedにすると
f:id:kikutaro777:20130623010610j:plain

ちゃんとカウントアップしてる!
おお、CDI管理対象BeanでViewScopedになってる!!!(っぽい)
※ぽい、とつけたのは、このサンプルでは厳密なViewScopedの確認とは言えないため;

で、Java EE 7のJavaDocをみにいってみると
http://docs.oracle.com/javaee/7/api/

f:id:kikutaro777:20130623011051j:plain

上記はキャプチャの一部なので、実際ページを見るのをおススメしますが、説明読む限りCDIでViewScopedで間違いないかと(^^;

これは超嬉しいです!!
なお試した環境は、NetBeans7.3.1でWebアプリケーションを作成し、Java EE 7,、GlassFish4.0を選んで作ったものです。

JavaでActiveDirectoryでの認証ができたー

Javaで(正しくはJava EEから)Active Directoryに接続するための準備が終わり、実装・テストも無事完了しました。

準備の過去記事は以下に。

コードはわりとシンプルで、とりあえず今まで設定したレベルの単純なADであれば以下で認証できました。

Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.PROVIDER_URL, "ldap://hogehoge:389");
env.put(Context.SECURITY_PRINCIPAL, "makimaki" + "@hogedomain.hoge");
env.put(Context.SECURITY_CREDENTIALS, "makimaki19881006");
        
DirContext ctx;
try {
    ctx = new InitialDirContext(env);
    ctx.close();
    //"AD認証成功"
} catch (NamingException ex) {
    //"AD認証失敗";
}

Hashtable使うとNetBeans君が「ォィォィ」って警告だすのですが、InitialDirContextの引数がHashtableっていうので何とも。

ちなみに本実装では

  • CDIのalternativeを使って、普通の自前ログイン認証とAD認証をbeans.xmlでスイッチできるようにしたり
  • サンプルコードで書いた各種パラメータ値(simpleとかldapのURLとか)は外部ファイルで設定できるようにしたり

などをしました。

JavaでのAD認証、当初の想定より早く実装が終わって良かったー。

Java EE 6のDIで理解していなかったこと

今の開発では、メモリの懸念などもあり、なるべくSessionScopeなBackingBeanを利用しないようにしています。かといって完全に取り除けるものでもないので、一部は当然使っていますが。

で、今日はこのSessionScopeで、基礎的な所をちゃんと理解していなかったなぁ…と結構ショックに思うことがあったので備忘としてまとめようかと…。

いかにも素人ちっくな恥ずかしい内容、かつ、まだ色々理解できていないんじゃないか…という不安もあるので「違うよ!」「おかしいよ!」とか突っ込みあればお願いします(^^;

まず、結論から書くと

SessionScopeの(今回はCDI)管理対象BeanをInjectしたとき、同一セッション下であれば、以降のInjectでは同じインスタンスが注入される

ことをわかっていませんでした。なんか上手く説明できていないので、具体例を書くと。

以下のようなSessionScopedのBackingBeanを定義して

package jp.co.hoge.cdiconfirmation;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named(value = "sessionScoped")
@SessionScoped
public class SessionScopedData implements Serializable{
    
    private String test;

    @PostConstruct
    public void init(){
        test = "キープしてる?";
    }

    //testのsetter getterを省略
}

さらにこいつを別のBackingBeanでInjectします。こっちはRequestScoped。

package jp.co.hoge.cdiconfirmation;

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

@Named(value = "indexBean")
@RequestScoped
public class IndexBean {

    @Inject
    private SessionScopedData data1;
    
    @Inject
    private SessionScopedData data2;
    
    private String output;

    @PostConstruct
    public void init(){
        System.out.println(data1.getTest());
        System.out.println(data2.getTest());
        
        data1.setTest("どうなる?");
        
        System.out.println(data1.getTest());
        System.out.println(data2.getTest());
    }

    // outputのsetter getterは省略
    // outputはBackingBeanを起動するためにViewが参照してる変数
}

自分は今まで、Inject=明示しないnewのようなもの、と理解していたので、上記定義だとdata1とdata2のインスタンスは別ものになるものと思っていました。

上記を実行すると

f:id:kikutaro777:20130416225408j:plain

となります。data1のインスタンスにだけ「どうなる?」をセットしたのですが、data2にも反映されています。というわけで、data1、data2の変数ともに参照先のインスタンスは同じです。

知らなかった… orz

で、1行だけ加えて

package jp.co.hoge.cdiconfirmation;

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

@Named(value = "indexBean")
@RequestScoped
public class IndexBean {

    @Inject
    private SessionScopedData data1;
    
    @Inject
    private SessionScopedData data2;
    
    private String output;

    @PostConstruct
    public void init(){
        System.out.println(data1.getTest());
        System.out.println(data2.getTest());
        
        // data2 を明示的にnewする
        data2 = new SessionScopedData();

        data1.setTest("どうなる?");
        
        System.out.println(data1.getTest());
        System.out.println(data2.getTest());
    }

    // outputのsetter getterは省略
    // outputはBackingBeanを起動するためにViewが参照してる変数
}

として、data2を明示的にnewして実行すると

f:id:kikutaro777:20130416225500j:plain

となりました。data2の参照先が別のインスタンスとなったようです。
nullになってるのも「ほぉ」という感じ(InjectじゃなくnewしたのでPostConstructは実行されないってことかなと)

Inject = 自動でやってくれるnew

とか思っていましたが、SessionScopeなインスタンスをInjectする際は違うのですね。。

詳しい方々からすると「何をあたりまえなことを…」という感じかも…ですが、自分のようにJava EE初心者だとこういう基礎的な所で考え違いをしていたり…。精進あるのみ。

Java EE6の開発でよく悩むこと ~ コールバックを例に ~

Java EE6の開発をしていて、「自分がやっていることは正しいのか…」と悩み、迷うことがあります。
わかりやすく自分が実際に迷った道を書いてみます。

例題がJava SEで書かれている時

Javaでコールバックを実装したいなー、と思って以下のサイト情報を見つけました。

Java コールバック関数

わかりやすい(^^)

ちなみに、いきなり脱線ですがJavaのコールバックの情報
やはり上記サイトのようにインタフェース利用するのがメジャーなんですかね。

アノテーション使う例もあるようです。

で、本題ですが、先のサイトではMain関数があって、Java SEでのサンプルコードとなっています。

じゃあ、Java EEになると…?と一瞬止まりますが、まあここは何とかなります。

サイトのソースをそのままに、Mainクラスだけを書き換えると多分こんな感じかと↓

package jp.co.hoge.bean;

import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import jp.co.hoge.callback.A;
import jp.co.hoge.callback.B;
import jp.co.hoge.callback.MyInterface;

@Named(value = "main")
@RequestScoped
public class MainBean implements Serializable{
    
    @Inject
    A a;
    
    @Inject
    B b;
    
    public MainBean(){
        
    }
    
    public void btnClick(){
        testCallback(a);
        testCallback(b);
    }
    
    private void testCallback(MyInterface myinterface){
        myinterface.doit();
    }
}

上記はCDI管理対象Beanを利用してます。
ここで既に違ってたら恥ずかしい…ですが…。

で、main関数の代わりに、ボタンが押されたらコールバック処理を各々呼ぶ、みたいな記述にしてます。

Java EEだと…

上記の単純な例は普通に書けるのがわかりました。

でも実際には、クラスAやクラスBの中身では、EJBを呼び出したりとか、色々したいわけです。

例えば以下のような単純なEJBを用意します。

package jp.co.hoge.business;

import javax.ejb.Stateless;

@Stateless
public class SomethingEjb {

    public String callEjb(){
        return "EJBの実装だよ";
    }

}

現実的にはDB処理とかになりますが、例を簡単にするために上記の定義とします。

POJOからEJBを呼ぶ…?

で、自分の場合、ここら辺で「ふにゃ?」となります。

以下のようなことを書いちゃったりします。
(Bクラスを書き換え例にします)

package jp.co.hoge.callback;

import javax.inject.Inject;
import jp.co.hoge.business.SomethingEjb;

public class B implements MyInterface{
    
    @Inject
    SomethingEjb ejb;

    @Override
    public void doit() {
        System.out.println("クラスBの実装");
        ejb.callEjb();
    }
}

「Injectすればいいんじゃないの、動くんじゃね」と悪魔がささやいたり…。

でも、ふと我に返って「それってCDI管理対象Beanの話でしょ!」と天使君がささやきます。

実際に上記を実行すると、落ちたりはしませんが、EJBとして機能しないためか

情報: クラスBの実装

としか出ませんでした。(Java EE6 + GlassFish 3.1.2.2)

CDI管理対象BeanからEJBを呼ぶ

というわけで次のように書きます。
(Aクラスを書き換え例にします)

package jp.co.hoge.callback;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import jp.co.hoge.business.SomethingEjb;

@Named
@SessionScoped
public class A implements MyInterface, Serializable{

    @Inject
    SomethingEjb ejb;
    
    @Override
    public void doit() {
        System.out.println("クラスAの実装");
        System.out.println(ejb.callEjb());
    }
    
}

実行すると

情報: クラスAの実装
情報: EJBの実装だよ

おー出た出た。大丈夫だ。

正しい道に進んでいるのかな…

なんか変に悩んでしまうのは、

Java SEの例だったPOJOをCDI管理対象Beanとかにしていいの?

とか変に悩んだりします。

なんかこういうことやってると実は後々メモリの問題とかやばいよ、みたいなことだったりするのか
そういう辺りが全然わからなくて…(^^;
普通はこういう風に書くんだぜ、という例もあまり見なくて…うーんって悩んだり。

同じような悩みをされる人はいるのでしょうか。。。

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村