Can an EJB server send an event to the EJB client side?

I wonder if something can be done on these lines:

1) Server side (EJB class)

@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) Client side

 //(...) SomeEJBRemote ejb = initialContext.lookup("SomeEJBRemote"); ejb.addListener(this); void EJBEventListener(SomeEvent event){ System.out.println("EJB server has sent an event!"); } 

A) Is there anything in the Java EE specification that allows this?

B) I know that JBoss allows some kind of bi-directional communication, but can I make just this example?

C) Is there something similar in OpenEJB (or TOMEE)?

+4
source share
2 answers

This is easy to do with the built-in EJB and MDB container in the client. We have an example that does just that.

Check out the monitor module in this example .

At 10,000 feet, this example does the following:

server side:

  • @Stateless bean that terminates access to EntityManager
  • JMS message sent by topic to all add / delete operations

on the client side:

  • Incoming EJB Container / MDB Messages
  • Upon receipt, a notification is issued to the user through java.awt.SystemTray

So, the interesting thing about this method is that it is completely transactional - EntityManager updates and sent JMS messages are part of the transaction. If the database update fails, a JMS message will not be sent.

Here is 100% of the client code from this example. It is not necessary to do much that is described.

Client "main" class

 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 Client Side

 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 client file

This configures the built-in EJB container. You can do this in code too.

 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 
+4
source

No, there is nothing like this in EJB. I would suggest that the client either listen to the JMS queue / topic. Alternatively, the client can export the listener object to RMI (in fact, it becomes the server itself), and then transfer the link to the server; this method will require some more infrastructure.

+1
source

Source: https://habr.com/ru/post/1381521/


All Articles