2012-05-31 72 views
0

我使用MySQL 5.5,Glassfish 3.1.2和獨立的Swing客戶端(JRE 6_u32)構建了一個三層應用程序。我計劃在Glassfish服務器上運行GUI更新服務,以便當另一個用戶創建,修改或刪除@Entity帶註釋的對象時,當前連接到應用程序服務器的任何用戶都會得到通知。Java-EE6:什麼類型的會話Bean用作JMS主題提供程序?

爲此目的,只要實體監聽器調用任何回調方法(@PostPersist,@PostUpdate,@PostRemove),我就會規劃一個會話Bean,它充當JMS主題生產者。獨立的Swing客戶端因此充當該主題的JMS消息消費者。

我的應用程序由3個項目組成。首先,EJB項目在服務器容器中運行,並保存外觀會話bean,這是一個包含@Entity註釋類和遠程外觀接口的類庫項目(該項目由EJB項目和獨立的swing客戶端共享以用於內部 - 通信目的),最後是管理GUI的獨立搖擺客戶端。 @Singleton類是classlib項目的一部分,因此我不能在那裏使用依賴注入。此外,我認爲這正是問題所在,@Singleton類不是容器管理的,因爲它被打包在它自己的jar-lib中,並被EJB項目引用(必須使用JNDI查找)。

你會推薦什麼樣的會話Bean來在應用程序服務器上實現主題消息生產者?單身,有狀態,無狀態,消息驅動?

這是我的singelton會話bean,因爲它現在是。問題是,@PostConstruct帶註釋的initConnection方法不知何故被調用。當publishCreated()被調用時,字段'session'和'publisher'爲空...

任何想法如何解決這個問題?提前謝謝了!

@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); 
     } 
    } 

} 
+0

您是否曾嘗試將'@ Startup'註釋添加到您的單例bean中。 –

+0

嗨nayan。感謝您的建議。我已經嘗試過使用@Startup,但後來發現一個異常,無法建立與主題的連接。可能是因爲容器試圖在JMS系統啓動之前實例化單例...任何其他想法如何解決這個問題? – salocinx

回答

1

其服務器的責任,注入的依賴,同時初始化豆。您可以嘗試使用註釋來注入這些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。

+0

感謝nayan。我忘了提到一個重要的事實。我的應用程序由3個項目組成。首先,EJB項目在服務器容器中運行,一個包含實體類和遠程外觀接口(這個接口由EJB和客戶端共享以進行相互通信)的類庫,最後是一個獨立的swing客戶端。 @ Singleton類是classlib項目的一部分,因此我不能在那裏使用依賴注入。此外,我認爲這正是問題所在,@Singleton類不是容器管理的。是否有另一種可能性來實現自動初始化? – salocinx

+0

@salocinx由於它不是EJB項目的一部分,並且沒有與任何應用程序服務器一起運行,所以這些註釋將不起作用。我認爲classlib在這裏是普通的java項目。你不能將singleton移動到EJB項目,並且classlib在GUI和EJB項目之間充當中介。另外我認爲實體監聽器是EJB項目的一部分,所以從那裏你可以產生消息,單身人士也將在同一個應用程序。 –

+0

@ Nayan。不幸的是,實體監聽器也是classlib項目的一部分,因爲@ Entity註釋類留在了classlib項目中,以便在EJB項目和獨立swing客戶端之間進行相互通信。將@ Singleton消息生產者移動到EJB,將實體監聽器和@實體類留在classlib中,然後當實體監聽器觸發事件​​時調用單例中的業務方法?或者在這種情況下你會如何設計一箇中介? – salocinx