1. 概要

この記事では、統合SpringとリモートエンタープライズJava Beans(EJB)の方法を示します。

これを行うには、いくつかのEJBと必要なリモートインターフェイスを作成してから、それらをJEEコンテナ内で実行します。 その後、Springアプリケーションを起動し、リモートインターフェースを使用して、Beanをインスタンス化し、リモート呼び出しを実行できるようにします。

EJBとは何か、またはEJBがどのように機能するかについて疑問がある場合は、トピックここに関する紹介記事をすでに公開しています。

2. EJBセットアップ

リモートインターフェイスとEJB実装を作成する必要があります。 それらを使用可能にするには、Beanを保持および管理するためのコンテナーも必要です。

2.1. EJBリモートインターフェース

まず、2つの非常に単純なBeanを定義することから始めましょう。1つはステートレスで、もう1つはステートフルです。

それらのインターフェースから始めましょう:

@Remote
public interface HelloStatefulWorld {
    int howManyTimes();
    String getHelloWorld();
}

@Remote
public interface HelloStatelessWorld {
    String getHelloWorld();
}

2.2. EJBの実装

それでは、リモートEJBインターフェースを実装しましょう。

@Stateful(name = "HelloStatefulWorld")
public class HelloStatefulWorldBean implements HelloStatefulWorld {

    private int howManyTimes = 0;

    public int howManyTimes() {
        return howManyTimes;
    }

    public String getHelloWorld() {
        howManyTimes++;
        return "Hello Stateful World";
    }
}

@Stateless(name = "HelloStatelessWorld")
public class HelloStatelessWorldBean implements HelloStatelessWorld {

    public String getHelloWorld() {
        return "Hello Stateless World!";
    }
}

ステートフルビーンズとステートレスビーンズがなじみのないものに聞こえる場合は、この紹介記事が役立つ場合があります。

2.3. EJBコンテナ

コードは任意のJEEコンテナーで実行できますが、実用性を高めるために、Wildflyと cargoMavenプラグインを使用して手間のかかる作業を行います。

<plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven2-plugin</artifactId>
    <version>1.6.1</version>
    <configuration>
        <container>
            <containerId>wildfly10x</containerId>
            <zipUrlInstaller>
                <url>
                  http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final.zip
                </url>
            </zipUrlInstaller>
        </container>
        <configuration>
            <properties>
                <cargo.hostname>127.0.0.1</cargo.hostname>
                <cargo.jboss.configuration>standalone-full</cargo.jboss.configuration>
                <cargo.jboss.management-http.port>9990</cargo.jboss.management-http.port>
                <cargo.servlet.users>testUser:admin1234!</cargo.servlet.users>
            </properties>
        </configuration>
    </configuration>
</plugin>

2.4. EJBの実行

これらを構成すると、Mavenコマンドラインから直接コンテナーを実行できます。

mvn clean package cargo:run -Pwildfly-standalone

これで、BeanをホストするWildflyの作業インスタンスができました。 これはログ行で確認できます。

java:global/ejb-remote-for-spring/HelloStatefulWorld!com.baeldung.ejb.tutorial.HelloStatefulWorld
java:app/ejb-remote-for-spring/HelloStatefulWorld!com.baeldung.ejb.tutorial.HelloStatefulWorld
java:module/HelloStatefulWorld!com.baeldung.ejb.tutorial.HelloStatefulWorld
java:jboss/exported/ejb-remote-for-spring/HelloStatefulWorld!com.baeldung.ejb.tutorial.HelloStatefulWorld
java:global/ejb-remote-for-spring/HelloStatefulWorld
java:app/ejb-remote-for-spring/HelloStatefulWorld
java:module/HelloStatefulWorld

java:global/ejb-remote-for-spring/HelloStatelessWorld!com.baeldung.ejb.tutorial.HelloStatelessWorld
java:app/ejb-remote-for-spring/HelloStatelessWorld!com.baeldung.ejb.tutorial.HelloStatelessWorld
java:module/HelloStatelessWorld!com.baeldung.ejb.tutorial.HelloStatelessWorld
java:jboss/exported/ejb-remote-for-spring/HelloStatelessWorld!com.baeldung.ejb.tutorial.HelloStatelessWorld
java:global/ejb-remote-for-spring/HelloStatelessWorld
java:app/ejb-remote-for-spring/HelloStatelessWorld
java:module/HelloStatelessWorld

3. 春のセットアップ

これで、JEEコンテナーが稼働し、EJBがデプロイされたので、Springアプリケーションを開始できます。 spring -boot-web を使用して手動でテストしやすくしますが、リモート呼び出しでは必須ではありません。

3.1. Mavenの依存関係

リモートEJBに接続できるようにするには、WildflyEJBクライアントライブラリとリモートインターフェイスが必要です。

<dependency>
    <groupId>org.wildfly</groupId>
    <artifactId>wildfly-ejb-client-bom</artifactId>
    <version>10.1.0.Final</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.baeldung.spring.ejb</groupId>
    <artifactId>ejb-remote-for-spring</artifactId>
    <version>1.0.1</version>
    <type>ejb</type>
</dependency>

wildfly-ejb-client-bom の最後のバージョンは、ここにあります。

3.2. ネーミング戦略のコンテキスト

クラスパスにこれらの依存関係があると、 javax.naming.Contextをインスタンス化して、リモートBeanのルックアップを実行できます。 これをSpringBeanとして作成し、必要なときに自動配線できるようにします。

@Bean   
public Context context() throws NamingException {
    Properties jndiProps = new Properties();
    jndiProps.put("java.naming.factory.initial", 
      "org.jboss.naming.remote.client.InitialContextFactory");
    jndiProps.put("jboss.naming.client.ejb.context", true);
    jndiProps.put("java.naming.provider.url", 
      "http-remoting://localhost:8080");
    return new InitialContext(jndiProps);
}

プロパティは、リモートURLと命名戦略コンテキストの両方に通知するために必要です。

3.3. JNDIパターン

リモートBeanをSpringコンテナー内に配線する前に、それらに到達する方法を知る必要があります。 このために、それらのJNDIバインディングを使用します。 これらのバインディングの標準パターンを見てみましょう。

${appName}/${moduleName}/${distinctName}/${beanName}!${viewClassName}

耳の代わりに単純なjarをデプロイし、名前を明示的に設定しなかったため、appNameとdistinctNameがないことに注意してください。 何か奇妙に思われる場合に備えて、EJBイントロの記事に詳細があります。

このパターンを使用して、リモートBeanをSpringBeanにバインドします。

3.4. 春の豆を作る

EJBに到達するには、前述のJNDIを使用します。エンタープライズBeanがデプロイされているかどうかを確認するために使用したログ行を覚えていますか?

その情報が現在使用されていることがわかります。

@Bean
public HelloStatelessWorld helloStatelessWorld(Context context) 
  throws NamingException {
 
    return (HelloStatelessWorld) 
      context.lookup(this.getFullName(HelloStatelessWorld.class));
}
@Bean
public HelloStatefulWorld helloStatefulWorld(Context context) 
  throws NamingException {
 
    return (HelloStatefulWorld) 
      context.lookup(this.getFullName(HelloStatefulWorld.class));
}
private String getFullName(Class classType) {
    String moduleName = "ejb-remote-for-spring/";
    String beanName = classType.getSimpleName();
    String viewClassName = classType.getName();
    return moduleName + beanName + "!" + viewClassName;
}

正しい完全なJNDIバインディングに十分注意する必要があります。そうしないと、コンテキストがリモートEJBに到達して、必要な基盤インフラストラクチャを作成できなくなります。

メソッドlookup from Context は、必要なbeanが見つからない場合に、NamingExceptionをスローすることに注意してください。

4. 統合

すべてが整ったら、 Beanをコントローラーに注入できるため、配線が正しいかどうかをテストできます。

@RestController
public class HomeEndpoint {
 
    // ...
 
    @GetMapping("/stateless")
    public String getStateless() {
        return helloStatelessWorld.getHelloWorld();
    }
    
    @GetMapping("/stateful")
    public String getStateful() {
        return helloStatefulWorld.getHelloWorld()
          + " called " + helloStatefulWorld.howManyTimes() + " times";
    }
}

Springサーバーを起動して、いくつかのログを確認しましょう。 次の行が表示され、すべてがOKであることを示します。

EJBCLIENT000013: Successful version handshake completed

それでは、ステートレスbeanをテストしてみましょう。 いくつかのcurlコマンドを試して、それらが期待どおりに動作していることを確認できます。

curl http://localhost:8081/stateless
Hello Stateless World!

そして、ステートフルなものを確認しましょう。

curl http://localhost:8081/stateful
Hello Stateful World called 1 times

curl http://localhost:8081/stateful
Hello Stateful World called 2 times

5. 結論

この記事では、SpringをEJBに統合し、JEEコンテナをリモート呼び出しする方法を学びました。 2つのリモートEJBインターフェースを作成し、SpringBeansを使用してそれらを透過的に呼び出すことができました。

Springは広く採用されていますが、EJBは依然としてエンタープライズ環境で人気があり、この簡単な例では、JakartaEEの分散ゲインとSpringの使いやすさの両方を利用できることを示しました。アプリケーション。

いつものように、コードはGitHubにあります。