2011-11-16 91 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