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();
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:
source share