// // ERCNPublisher.java // Project ERChangeNotificationJMS // // Created by tatsuya on Sat Aug 31 2002 // package er.changenotification; import javax.jms.DeliveryMode; import javax.jms.JMSException; import javax.jms.ObjectMessage; import javax.jms.Session; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import com.webobjects.foundation.NSLog; import com.webobjects.foundation.NSNotification; /** * ERCNPublisher sends change notifications to other application instances via * JMS server. It observes changes in the default EOObjectStoreCoordinator and * creates an ERCNSnapshot object when EOEditingContext saveChanges is performed. * <p> * There must be exactly one instance of the ERCNPublisher on the application * and registered to the NSNotificationCenter, but its publishChange method * will be executed by application's multiple worker threads concurrently. * Since JMS session object is limited for serial use (single threaded use), * ERCNPublisher prepares a JMS session object per thread so that each worker * threads can perform the operation concurrently. */ class ERCNPublisher { private ERCNNotificationCoordinator _coordinator; ERCNPublisher(ERCNNotificationCoordinator coordinator) { _coordinator = coordinator; } public void publishChange(NSNotification notification) { if (! _coordinator.isConnected()) return; ERCNSnapshot snapshot = new ERCNSnapshot(notification); if (snapshot.shouldPostChange()) { final int deliveryMode = DeliveryMode.NON_PERSISTENT; final int priority = 4; // 0:Low -- 9:High // set TTL to 63 minutes; little longer than the default // value of ec.defaultFetchTimestampLag() final long timeToLive = 63 * 60 * 1000; try { TopicSession topicSession = _topicSession(); if (topicSession != null) { ObjectMessage message = topicSession.createObjectMessage(snapshot); Topic topic = _coordinator.topic(); _topicPublisher(topic, topicSession).publish(topic, message, deliveryMode, priority, timeToLive); if (NSLog.debug.isEnabled()) NSLog.debug.appendln(ERCNNotificationCoordinator.LOG_HEADER + "Posted a message with snapshot: " + snapshot); } // java.rmi.ConnectException -- server is down (publish) // java.rmi.UnmarshalException -- version // javax.jms.IllegalStateException - Cannot perform operation - session has been closed } catch (JMSException ex) { NSLog.err.appendln(ERCNNotificationCoordinator.LOG_HEADER + "Failed to poste a snapshot: " + ex.getMessage()); } } } private TopicSession _topicSession() { TopicSession topicSession = null; try { TopicConnection connection = _coordinator.connection(); topicSession = connection.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE); } catch (JMSException ex) { // javax.jms.IllegalStateException - Cannot perform operation - session has been closed NSLog.err.appendln(ERCNNotificationCoordinator.LOG_HEADER + "Failed to create a JMS topic session: " + ex.getMessage()); } return topicSession; } private TopicPublisher _topicPublisher(Topic topic, TopicSession topicSession) { TopicPublisher topicPublisher = null; try { topicPublisher = topicSession.createPublisher(topic); } catch (JMSException ex) { NSLog.err.appendln(ERCNNotificationCoordinator.LOG_HEADER + "Failed to create a JMS topic publisher: " + ex.getMessage()); } return topicPublisher; } synchronized void terminate() { // do nothing } }