4

ステートレス セッション Bean (EJB) 内で作成された接続をいつ閉じるかについて、一般的な質問があります。接続は ActiveMQ へのものであり、Bean のコンストラクター内で作成されます。その後、接続はメソッド内で使用されます。この接続を閉じる適切な時間/場所はいつなのか疑問に思っています。

Bean を使用するクラスによって呼び出される必要がある、接続を閉じるための別のメソッドを持つことは適切でしょうか? または、それを使用するメソッド内で接続を閉じる必要がありますか? コンストラクターで接続が開かれているため、接続を閉じてから、現在閉じている接続でその Bean を再利用するのではないかと心配しています。ここにいくつかのコードがあります:

@Stateless
@LocalBean
public class SendEventsBean {


private static String brokerURL = ".......";
private static transient ConnectionFactory factory;
private transient Connection connection;
private transient Session session;
private transient MessageProducer producer;

public SendEventsBean() {
    factory = new ActiveMQConnectionFactory(brokerURL);
    try {
        connection = factory.createConnection();
        connection.start();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        producer = session.createProducer(null);
    } catch (JMSException e) {
        e.printStackTrace();
    }
}

public void sendEvent(String id, String description, String area) {

    Destination destination;
    try {
        destination = session.createQueue("FWT." + "events");
        TextMessage message = session.createTextMessage(id + " " + description + " " + area);
        producer.send(destination, message);
    } catch (JMSException e) {
        e.printStackTrace();
    }   
}

public void close() throws JMSException {
    if (connection != null) {
        connection.close();
    }
}
}

ご覧のとおり、現在、イベントの送信後に Bean を使用してクラスによって呼び出される別の close メソッドがあります。これは合法ですか、それともトラブルを求めていますか? 私は EJB の経験がなく、どんな提案も歓迎します。Bean は、@EJB アノテーションを使用して呼び出しクラスに注入されます。

4

6 に答える 6

3

受け入れられた答えは、毎回新しい接続、新しいセッション、および新しいプロデューサーを作成することを推奨していることがわかります。また、オラクルは、新しい接続を作成するのは非常に安価であると述べています。それは本当ではありません。使用しているアプリケーション サーバーによって異なります。

たとえば、Weblogicのドキュメントには、リソースとセッションの作成にはコストがかかることが明確に記載されています。ApacheMQ の方が優れているかどうかはわかりません。

接続を 1 つだけ作成して保持することをお勧めします。EJB で参照を保持しないでください。ただし、保持してください。シングルトンで、アプリケーション スコープごと、セッション スコープごと、好きな場所で。

それを行うと、接続が失敗する可能性があるという追加の問題が発生します。キャッシュされた接続がサーバーから切断されたかどうかを知りたいと思うでしょう。自動再接続機能はうまく機能しません。特に自動移行可能な JMS サーバーの場合。

Connection.setExceptionListener(ExceptionListener)を使用してエラーリスナーを実装できます。

onError(method) が呼び出されると、キャッシュをクリアできます。

于 2016-11-14T16:00:59.513 に答える
2

JMS ファクトリ構成オプションをセッション Bean に格納するのはあまり適切ではありません。ここで説明されているように、サーバー レベルでより適切に保存します: https://www.initworks.com/wiki/display/public/JMS+messages+from+EJBs+on+GlassFish

サーバーは接続プールを持つことができ、パフォーマンスに優れています。また、サーバーは必要に応じて接続を自動的に閉じます。コードでそれを処理する必要はありません。

于 2013-11-04T16:37:41.357 に答える
2

JMS API リソースは、JMS API 接続と JMS API セッションです。一般に、使用されなくなった JMS リソースを解放することが重要です。従うべきいくつかの有用なプラクティスを次に示します。

ビジネス メソッドの有効期間だけ JMS API リソースを維持したい場合は、メソッド内の finally ブロックでリソースを閉じることをお勧めします。エンタープライズ Bean インスタンスの存続期間にわたって JMS API リソースを維持する場合は、コンポーネントの ejbCreate メソッドを使用してリソースを作成し、コンポーネントの ejbRemove メソッドを使用してリソースを閉じることをお勧めします。ステートフル セッション Bean またはエンティティ Bean を使用していて、JMS API リソースをキャッシュされた状態で維持したい場合は、ejbPassivate メソッドでリソースを閉じて、その値を null に設定し、ejbActivate メソッドでリソースを再度作成する必要があります。方法。

メッセージ駆動型 Bean の ejbCreate メソッドを使用して JMS API 接続を作成した場合、通常は ejbRemove メソッドを使用して接続を閉じます。

于 2013-11-04T16:24:36.143 に答える
2

エンタープライズ Bean には、そのようなアクティビティに使用できるライフサイクル メソッドがいくつかあります。

@PostConstruct
private void onCreate() {
    // basically what you have in your present constructor
}

@PreDestroy
private void onDestroy() {
    // housecleaning goes here
}

編集 - ここで ActiveMQ を「生の」方法で使用しているように見えます。おそらく、それはアプリサーバーのネイティブ JMS コンポーネントではないためです。しかし、これは EJB コードのブローカー URL のようなかなり低レベルのものにつながります。サーバーの組み込み JMS インフラストラクチャを使用すると、もちろん可能であれば、全体的により良いソリューションにつながるため、なぜこのようにしているのかを知っておくと役立つ場合があります。

于 2013-11-04T16:25:08.843 に答える