2011-11-16 123 views
4

我不知道這是可以做到的東西沿着這些路線:EJB服務器端可以將事件發送給EJB客戶端嗎?

1)服務器端(EJB類)

@Statefull 
public class SomeEJB implements SomeEJBRemote { 

@Resource 
private SessionContext sessionContext; 

//(...) 
public void someMethod(Record record){ 
    //(...) 
    //Situation that requires the server to alert all registered listeners 
    if(specialSituation){ 
     sessionContext.fireEventToListeners(new SomeEvent()); 
    } 

    //Do something else... 
} 
} 

2)客戶端

//(...) 
SomeEJBRemote ejb = initialContext.lookup("SomeEJBRemote"); 
ejb.addListener(this); 

void EJBEventListener(SomeEvent event){ 
    System.out.println("EJB server has sent an event!"); 
} 

A)有什麼在允許這個的Java EE規範中? B)我知道JBoss允許某種雙向通信,但我可以像這樣做嗎?

C)在OpenEJB(或TOMEE)中有這樣的東西嗎?

回答

1

不,在EJB中沒有這樣的東西。我建議讓客戶端聽JMS隊列/主題。或者,客戶端可以將偵聽器對象導出到RMI(實際成爲服務器本身),然後將引用傳遞給服務器;這項技術需要相當多的基礎設施。

+0

我想過了,但RMI *和*開銷(如您所說,對於基礎設施)的複製通信渠道的安全要求阻止我們使用它。 : - / –

4

使用客戶端中的嵌入式EJB容器和MDB很容易。我們有一個完全如此的例子。

查看模塊this example

10,000英尺這個例子中執行以下操作:

服務器端:

  • 換到接入@Stateless bean的一個EntityManager
  • 發送到主題上的所有
  • JMS消息添加/刪除操作

客戶端:

  • 嵌入式EJB容器/ MDB接收消息
  • 在收到通知經java.awt.SystemTray

向用戶發出所以關於這項技術的有趣的事情是,它是完全事務 - EntityManager的更新發送的JMS消息都是交易的一部分。如果數據庫更新失敗,則不會發送JMS消息。

這裏是來自該示例的100%的客戶端代碼。不要花太多的精力去做所描述的事情。

客戶端 「主」 類

import javax.naming.InitialContext; 
import javax.naming.NamingException; 
import java.awt.AWTException; 
import java.awt.Image; 
import java.awt.MenuItem; 
import java.awt.PopupMenu; 
import java.awt.SystemTray; 
import java.awt.Toolkit; 
import java.awt.TrayIcon; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.net.MalformedURLException; 
import java.net.URL; 

public class NotificationMonitor { 
    private static TrayIcon trayIcon; 

    public static void main(String[] args) throws NamingException, InterruptedException, AWTException, MalformedURLException { 
     addSystemTrayIcon(); 

     // Boot the embedded EJB Container 
     new InitialContext(); 

     System.out.println("Starting monitor..."); 
    } 

    private static void addSystemTrayIcon() throws AWTException, MalformedURLException { 
     SystemTray tray = SystemTray.getSystemTray(); 

     URL moviepng = NotificationMonitor.class.getClassLoader().getResource("movie.png"); 
     Image image = Toolkit.getDefaultToolkit().getImage(moviepng); 

     ActionListener exitListener = new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("Exiting monitor..."); 
       System.exit(0); 
      } 
     }; 

     PopupMenu popup = new PopupMenu(); 
     MenuItem defaultItem = new MenuItem("Exit"); 
     defaultItem.addActionListener(exitListener); 
     popup.add(defaultItem); 

     trayIcon = new TrayIcon(image, "Notification Monitor", popup); 
     trayIcon.setImageAutoSize(true); 
     tray.add(trayIcon); 
    } 

    public static void showAlert(String message) { 
     synchronized (trayIcon) { 
      trayIcon.displayMessage("Alert received", message, TrayIcon.MessageType.WARNING); 
     } 
    } 
} 

客戶端MDB

import javax.ejb.ActivationConfigProperty; 
import javax.ejb.MessageDriven; 
import javax.jms.JMSException; 
import javax.jms.Message; 
import javax.jms.MessageListener; 
import javax.jms.TextMessage; 

@MessageDriven(activationConfig = { 
     @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), 
     @ActivationConfigProperty(propertyName = "destination", propertyValue = "notifications")}) 
public class NotificationsBean implements MessageListener { 

    public void onMessage(Message message) { 
     try { 
      TextMessage textMessage = (TextMessage) message; 
      String text = textMessage.getText(); 

      NotificationMonitor.showAlert(text); 
     } catch (JMSException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

客戶jndi.properties文件

這將配置嵌入式EJB容器。你也可以在代碼中做到這一點。

java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory 
Default\ JMS\ Resource\ Adapter=new://Resource?type=ActiveMQResourceAdapter 
Default\ JMS\ Resource\ Adapter.BrokerXmlConfig=broker:vm://localhost 
Default\ JMS\ Resource\ Adapter.ServerUrl=tcp://localhost:61616