2

次のように機能するEJBファクトリクラスを作成しようとしています。引数としてEJBのクラスを受け取るメソッドがあり、EJBにリモートインターフェイスがあるかどうか(例外をスローしない場合)と、します、それは関係するEJBを返します。

以下のコードはまさにこれを行います。ただし、返されるオブジェクトは、関連するBeanのリモート・インターフェースのタイプであり、Bean自体のタイプではありません。どうすればこれを変更できますか?ジェネリック型Tがメソッドに渡されるクラスと同じ型であることをJavaに伝える方法はありますか?

import java.util.Properties;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.naming.*;


public class EJBFactory
{

    private InitialContext ctx;

    public EJBFactory() throws NamingException {
        ctx = new InitialContext();
    }

    public EJBFactory(String host, String port) throws NamingException {
        Properties props = new Properties();
        props.setProperty("org.omg.CORBA.ORBInitialHost", host);
        props.setProperty("org.omg.CORBA.ORBInitialPort", port);
        ctx = new InitialContext(props);
    }
.
    // To improve: The object returned should be of the type ejbClass
    // instead of the remote interface, which it implements
    public <T> T createEJB(Class ejbClass) throws NamingException
    {
        Class remoteInterface = null;
        for(Class interface_: ejbClass.getInterfaces()) {
            if(interface_.isAnnotationPresent(Remote.class))
                remoteInterface = interface_;
        }

        if(remoteInterface == null)
            throw new  IllegalArgumentException(
                "EJB Requires a remote interface");

        // Get the stateless annotation, then get the jndiName
        Stateless stateless =
            (Stateless)ejbClass.getAnnotation(Stateless.class);
        String jndiName = stateless.mappedName();
        T ejbObj = (T) ctx.lookup(jndiName);
        return ejbObj;
    }

}

Factoryを使用した単体テストの例。

import junit.framework.TestCase;


public class SimpleEJBTest extends TestCase
{
    TestRemote testBean;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        EJBFactory ejbFactory = new EJBFactory();
        testBean = ejbFactory.createEJB(TestBean.class);
    }

    public void testSayHello() {
        assertEquals("Hello", testBean.sayHello());
    }
}

注:この例はGlassfishで機能しますが、他のアプリサーバーではテストしていません。

4

4 に答える 4

3

EJBのクライアントは、EJBが実装するローカル/リモートインターフェイスを介してEJBと対話します。クライアントアプリケーションは、実際のセッションBeanクラスインスタンスに直接アクセスすることはできません。これは、インスタンスのプーリングを可能にするために行われます。この場合、コンテナはEJBインスタンスを再利用してさまざまなリクエストを処理できます。

実際のBeanのオブジェクトにアクセスする必要がある理由がわかりません(明らかに私はあなたの要件を知らないため)。ただし、そのインスタンスを作成する必要がある場合は、リフレクションを使用して次のようClass.forName(className).newInstance();に作成できます。このように作成するインスタンスは、EJBではありません。それはただのPOJOです。

編集-junitテストに関するコメントの後:次のようにJavaSEからビジネスメソッドにアクセスする場合、実際にはEJBのメソッドを呼び出しています-インターフェイスを介して対話するだけです。したがって、ビジネスメソッドをテストする場合でも、JUnitテストでJNDIルックアップを介して取得したオブジェクトからテストできます。

//MyGreatBean implements MyGreat. MyGreat has @Remote, MyGreatBean has @Stateless
ref = jndiContext.lookup("MyGreatBean/remote");
MyGreat bean = (MyGreat) ref; 
String retValue = bean.businessMethod();
assertEquals("Success", retValue);

以前のコメントから、実際のEJBクラスにどのような種類のアノテーションが追加されているかを確認したいと思います。実際にビジネスメソッドを実行せずにそのような種類の確認を行いたい場合は、Classを使用してインスタンスを作成できます。 forName...上記のように。このようなインスタンスを作成する場合、「JavaEE」機能を実行しないメソッドのみを呼び出すことができます。たとえば、次のようなEJBクラスのメソッドを呼び出すことができます。

public String someMethod(){
       return "I am a POJO but I look like an EJB";
}
于 2009-08-17T18:10:29.620 に答える
1

EJBオブジェクトを取得できるとは思いません。インターフェースしか入手できません。createEJBはインターフェイスで呼び出す必要があり、インターフェイスを返します。

于 2009-08-06T14:51:44.470 に答える
0

交換してみてください

public <T> T createEJB(Class ejbClass) throws NamingException

public <T> T createEJB(Class<T> ejbClass) throws NamingException
于 2009-08-06T14:23:42.240 に答える
0

これを試してみませんか?

インターフェイスを作成します。@Remoteを作成します。@Statelessで注釈が付けられたejbは、上記で作成されたインターフェースを実装する必要があります。今、あなたがしているのと同じことをやってみてください。それはあなたに望ましい結果を与えるはずだと思います。IDEからコピーせずにここに入力すると、エラーが発生します。しかし、あなたは私が推測するドリフトを取得する必要があります。

@Remote
public interface Example{
   String some();
}

@stateless
public class ExampleBean implements Example{

}
于 2009-08-14T00:11:08.157 に答える