1. 概要

Enterprise Java Beans (EJB)は、分散型エンタープライズレベルアプリケーションの開発を簡素化することを目的としたJavaEE仕様のコア部分です。 EJBのライフサイクルは、 JBossWildFlyOracleGlassFishなどのアプリケーションサーバーによって処理されます。

EJBは、トランザクション処理、コンポーネントライフサイクル管理、依存性注入などのビジネスロジックに関連しない問題を処理するのはアプリケーションサーバー次第であるため、エンタープライズレベルのソフトウェアモジュールの実装を容易にする堅牢なプログラミングモデルを提供します。

さらに、EJBの基本概念をカバーする2つの記事をすでに公開しているので、こちらこちらをお気軽にチェックしてください。

このチュートリアルでは、WildFlyに基本的なEJBモジュールを実装し、JNDIを介してリモートクライアントからEJBを呼び出す方法を示します。

2. EJBモジュールの実装

ビジネスロジックは、1つまたは複数のローカル/リモートビジネスインターフェイス(ローカル/リモートビューとも呼ばれます)によって、またはインターフェイスを実装しないクラス(非ビューインターフェイス)を介して直接実装されます。

同じ環境に存在するクライアントからbeanにアクセスする場合、つまりローカルビジネスインターフェイスが使用されることに注意してください。 同じEARまたはWARファイルですが、Beanが別の環境からアクセスされる場合は、リモートビジネスインターフェイスが必要です。 別のJVMまたはアプリケーションサーバー。

1つのbeanだけで構成される基本的なEJBモジュールを作成しましょう。 Beanのビジネスロジックは単純で、特定のStringを大文字バージョンに変換することに限定されます。

2.1. リモートビジネスインターフェイスの定義

まず、@Remoteアノテーションで装飾された単一のリモートビジネスインターフェイスを定義しましょう。 EJB 3.x仕様によれば、これは必須です。Beanはリモートクライアントからアクセスされるためです。

@Remote
public interface TextProcessorRemote {
    String processText(String text);
}

2.2. ステートレスBeanの定義

次に、前述のリモートインターフェイスを実装してビジネスロジックを実現しましょう。

@Stateless
public class TextProcessorBean implements TextProcessorRemote {
    public String processText(String text) {
        return text.toUpperCase();
    }
}

TextProcessorBean クラスは、@Statelessアノテーションで装飾された単純なJavaクラスです。

ステートレスBeanは、定義上、異なるリクエスト間でインスタンスの状態を維持できる場合でも、クライアントとの会話状態を維持しません。 それらの対応するステートフルBeanは、会話状態を保持します。たとえば、アプリケーションサーバー用に作成するのに費用がかかります。

この場合、上記のクラスにはインスタンス状態がないため、ステートレスにすることができます。 状態がある場合、異なるクライアント要求間でそれを使用することはまったく意味がありません。

Beanの動作は決定論的です。つまり、適切に設計されたBeanのように、副作用はありません。入力 String を受け取り、その大文字バージョンを返すだけです。

2.3. Mavenの依存関係

次に、 javaee-api Mavenアーティファクトをモジュールに追加する必要があります。これにより、EJBに必要なものを含むすべてのJavaEE7仕様APIが提供されます。

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>

この時点で、基本的でありながら機能的なEJBモジュールを作成することができました。 すべての潜在的なクライアントが利用できるようにするには、アーティファクトをローカルのMavenリポジトリにJARファイルとして追加する必要があります。

2.4. ローカルリポジトリへのEJBモジュールのインストール

これを達成するためのいくつかの方法があります。 最も簡単な方法は、Mavenライフサイクルクリーン–インストールビルドフェーズを実行することです。

mvn clean install

このコマンドは、EJBモジュールを ejbmodule-1.0.jar(または pom.xml ファイルで指定された任意のアーティファクトID)としてローカルリポジトリにインストールします。 Mavenを使用してローカルJARをインストールする方法の詳細については、この記事を確認してください。

EJBモジュールがローカルリポジトリに正しくインストールされていると仮定すると、次のステップは、 TextProcessorBeanAPIを利用するリモートクライアントアプリケーションを開発することです。

3. リモートEJBクライアント

リモートEJBクライアントのビジネスロジックを非常にシンプルに保ちます。最初に、JNDIルックアップを実行してTextProcessorBeanプロキシを取得します。 その後、プロキシの processText()メソッドを呼び出します。

3.1. Mavenの依存関係

EJBクライアントが期待どおりに機能するには、次のMavenアーティファクトを含める必要があります。

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.wildfly</groupId>
    <artifactId>wildfly-ejb-client-bom</artifactId>
    <version>10.1.0.Final</version>
</dependency>
<dependency>
    <groupId>com.beldung.ejbmodule</groupId>
    <artifactId>ejbmodule</artifactId>
    <version>1.0</version>
</dependency>

javaee-api アーティファクトを含める理由は明らかですが、wildfly-ejb-client-bomを含めることはできません。 このアーティファクトはWildFlyでリモートEJB呼び出しを実行するために必要です。

最後になりましたが、以前のEJBモジュールをクライアントで使用できるようにする必要があるため、ejbmodule依存関係も追加しました。

3.2. EJBクライアントクラス

EJBクライアントがTextProcessorBeanのプロキシを呼び出すことを考えると、非常に実用的であり、クライアントクラスにTextApplicationという名前を付けます。

public class TextApplication {

    public static void main(String[] args) throws NamingException {
        TextProcessorRemote textProcessor = EJBFactory
          .createTextProcessorBeanFromJNDI("ejb:");
        System.out.print(textProcessor.processText("sample text"));
    }

    private static class EJBFactory {

        private static TextProcessorRemote createTextProcessorBeanFromJNDI
          (String namespace) throws NamingException {
            return lookupTextProcessorBean(namespace);
        }

        private static TextProcessorRemote lookupTextProcessorBean
          (String namespace) throws NamingException {
            Context ctx = createInitialContext();
            String appName = "";
            String moduleName = "EJBModule";
            String distinctName = "";
            String beanName = TextProcessorBean.class.getSimpleName();
            String viewClassName = TextProcessorRemote.class.getName();
            return (TextProcessorRemote) ctx.lookup(namespace 
              + appName + "/" + moduleName 
              + "/" + distinctName + "/" + beanName + "!" + viewClassName);
        }

        private static Context createInitialContext() throws NamingException {
            Properties jndiProperties = new Properties();
            jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, 
              "org.jboss.naming.remote.client.InitialContextFactory");
            jndiProperties.put(Context.URL_PKG_PREFIXES, 
              "org.jboss.ejb.client.naming");
            jndiProperties.put(Context.PROVIDER_URL, 
               "http-remoting://localhost:8080");
            jndiProperties.put("jboss.naming.client.ejb.context", true);
            return new InitialContext(jndiProperties);
        }
    }
}

簡単に言うと、 TextApplication クラスが行うのは、Beanプロキシを取得し、サンプル文字列を使用してその processText()メソッドを呼び出すことだけです。

実際のルックアップは、ネストされたクラス EJBFactory によって実行されます。このクラスは、最初にJNDI InitialContext インスタンスを作成し、次に必要なJNDIパラメーターをコンストラクターに渡し、最後にそれを使用してBeanをルックアップします。プロキシー。

ルックアップは、WildFly独自の「ejb:」名前空間を使用して実行されることに注意してください。 これにより、プロキシが明示的に呼び出されるまでクライアントがサーバーへの接続を延期するため、ルックアッププロセスが最適化されます。

「ejb」名前空間にまったく頼らずにbeanプロキシを検索できることも注目に値します。 ただし、レイジーネットワーク接続の追加の利点がすべて失われているため、クライアントのパフォーマンスが大幅に低下します

3.3. EJBコンテキストの設定

クライアントは、Beanルックアップを実行するために接続を確立するホストとポートを知っている必要があります。 この点で、クライアントは独自のWildFly EJBコンテキストを設定する必要があります。これは、クラスパス(通常は src / main / resources)に配置されたjboss-ejb-client.propertiesファイルで定義されます。 フォルダー:

endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=127.0.0.1
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options
  .SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=myusername
remote.connection.default.password=mypassword

このファイルは、WildFlyへの接続を確立するために必要なすべてのパラメーター(デフォルトのリモート接続数、デフォルトのホストとポート、およびユーザー資格情報を含む)を提供するため、かなり自明です。 この場合、接続は暗号化されていませんが、SSLが有効になっている場合は暗号化されている可能性があります。

最後に考慮すべきことは、接続に認証が必要な場合は、add-user.sh/add-user.batユーティリティを介してWildFlyにユーザーを追加する必要があるということです。

4. 結論

概説されたプロセスに厳密に従う限り、WildFlyでEJBルックアップを実行するのは簡単です。

いつものように、この記事に含まれているすべての例は、GitHub hereおよびhereで入手できます。