0

MySQL 5.5、Glassfish 3.1.2、およびスタンドアロンのSwingクライアント(JRE 6_u32)を使用して3層アプリケーションを構築しました。Glassfishサーバーで実行されるGUI更新サービスを計画しているので、別のユーザーが@Entity注釈付きオブジェクトを作成、変更、または削除したときに、アプリケーションサーバーに現在接続しているすべてのユーザーに通知されます。

そのために、エンティティリスナーによってコールバックメソッド(@ PostPersist、@ PostUpdate、@ PostRemove)が呼び出されるとすぐに、JMSトピックプロデューサーとして機能するセッションBeanを計画します。これにより、スタンドアロンのSwingクライアントは、トピックのJMSメッセージコンシューマーとして機能します。

私のアプリケーションは3つのプロジェクトで構成されています。まず、EJBプロジェクトウィッチはサーバーコンテナ内で実行され、ファサードセッションBeanを保持します。これは、@ Entity注釈付きクラスとリモートファサードインターフェイスを保持するクラスライブラリプロジェクトです(これは、EJBプロジェクトとスタンドアロンのswingクライアントによって共有されます。 -通信目的)そして最後に、GUIを管理するスタンドアロンのswingクライアント。@Singletonクラスはclasslibプロジェクトの一部であるため、そこで依存性注入を使用することはできません。さらに、これはまさに問題だと思います。@ Singletonクラスは、独自のjar-libにパックされ、EJBプロジェクトによって参照されるため(JNDIルックアップを使用する必要があるため)、コンテナー管理されません。

アプリケーションサーバーにトピックメッセージプロデューサーを実装するために、どのような種類のSession Beanをお勧めしますか?シングルトン、ステートフル、ステートレス、メッセージ駆動型?

これが、現在の私のsingeltonセッションBeanです。問題は、@PostConstructの注釈付きinitConnectionメソッドが何らかの理由で呼び出されないことです。publishCreated()が呼び出されている場合、フィールド「session」および「publisher」はnullになります。

この問題を解決する方法はありますか?よろしくお願いします!

@Singleton
public class UpdateService {

    private Destination topic;
    private ConnectionFactory factory;
    private Connection connection;
    private Session session;
    private MessageProducer producer;

    public UpdateService() { }

    @PostConstruct void initConnection() {
        try {
            InitialContext ctx = ServerContext.getInitialContext();
            factory = (TopicConnectionFactory)ctx.lookup("jms/TopicFactory");
            topic = (Topic)ctx.lookup("jms/TopicUpdate");
            connection = factory.createConnection();
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            producer = session.createProducer(topic);
        } catch (NamingException ex) {
            Logger.getLogger(UpdateService.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        } catch (JMSException ex) {
            Logger.getLogger(UpdateService.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        }
    }

    @PreDestroy void closeConnection() {
        try {
            session.close();
            connection.close();
        } catch (JMSException ex) {
            Logger.getLogger(UpdateService.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        }
    }

    @PostPersist void publishCreated(IUpdateableEntity entity) throws JMSException {
        if(session!=null && producer!=null) {
            ObjectMessage message = session.createObjectMessage(new UpdateMessage(entity, UpdateType.CREATED));
            producer.send(message);
        }
    }

    @PostUpdate void publishUpdated(IUpdateableEntity entity) throws JMSException {
        if(session!=null && producer!=null) {
            ObjectMessage message = session.createObjectMessage(new UpdateMessage(entity, UpdateType.MODIFIED));
            producer.send(message);
        }
    }

    @PostRemove void publishRemoved(IUpdateableEntity entity) throws JMSException {
        if(session!=null && producer!=null) {
            ObjectMessage message = session.createObjectMessage(new UpdateMessage(entity, UpdateType.REMOVED));
            producer.send(message);
        }
    }

}
4

1 に答える 1

1

Bean の初期化中に依存関係を注入するサーバーの責任。アノテーションを使用して、これらの JMS リソースを注入してみることができます。

@Startup
@Singleton
public class UpdateService {

    @Resource(mappedName = "jms/TopicFactory")
    private ConnectionFactory connectionFactory;

    @Resource(mappedName = "jms/TopicUpdate")
    private Topic replyToTestQueue;

    @PostConstruct
    void initConnection() {

          //-- Messaging Configuration 
    }
}

管理コンソールを使用して、これらのリソースが適切に構成されていることを確認してください。私はGlassfishに慣れていませんが、試してみましたがうまくいきました。

ただし、デフォルトでは、すべてのシングルトン メソッドはトランザクション対応でスレッド セーフであるため、明示的にロックすることで同時実行性を管理できます。それ以外の場合は、適切であればステートレス Bean を使用できます。

于 2012-05-31T18:40:12.373 に答える