Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- merged @zyro fixes

- add connection listener bridge ( to publish on browser:// namespace )
  • Loading branch information...
commit 6f3fdfccfae743a7efc0a76bea259d0044ed8bdc 1 parent 3538556
@smaldini authored
View
9 EventsPushGrailsPlugin.groovy
@@ -26,7 +26,7 @@ import org.springframework.util.ClassUtils
class EventsPushGrailsPlugin {
// the plugin version
- def version = "1.0.M6"
+ def version = "1.0.M7"
// the version or versions of Grails the plugin is designed for
def grailsVersion = "2.0 > *"
// the other plugins this plugin depends on
@@ -87,9 +87,6 @@ the server to the browser.
'description'('MeteorServlet')
'servlet-name'('MeteorServlet')
'servlet-class'(GrailsMeteorServlet.name)
- if (ClassUtils.isPresent("javax.servlet.AsyncContext", Thread.currentThread().getContextClassLoader())) {
- 'async-supported'(true)
- }
config?.servlet?.initParams?.each { initParam ->
if (initParam.key && initParam.value) {
'init-param' {
@@ -119,6 +116,10 @@ the server to the browser.
'load-on-startup'('0')
+
+ if (ClassUtils.isPresent("javax.servlet.AsyncContext", Thread.currentThread().getContextClassLoader())) {
+ 'async-supported'(true)
+ }
}
}
View
6 grails-app/services/org/groovy/grails/platform/push/TestService.groovy
@@ -35,11 +35,15 @@ class TestService {
@Listener(topic= 'sampleBro-1', namespace = 'browser')
def sampleBro(test) {
- println """--> $test"""
def ts=new TestDomain(name:'test')
ts.save() //This will trigger the GORM event 'afterInsert' where we have allowed for client listeners in TestEvents.groovy.
//any browsers using grailsEvents.on('afterInsert', function(data){...}); will receive a JSON from TestDomain
}
+
+ @Listener(namespace='browser')
+ def onDisconnect(event){
+ println 'disconnect'
+ }
}
View
13 src/java/grails/events/GrailsEventsAware.java
@@ -0,0 +1,13 @@
+package grails.events;
+
+import org.grails.plugin.platform.events.Events;
+
+/**
+ * Author: smaldini
+ * Date: 1/21/13
+ * Project: events-push
+ */
+public interface GrailsEventsAware {
+
+ void setGrailsEvents(Events grailsEvents);
+}
View
81 src/java/org/grails/plugin/platform/events/push/BridgeWSListener.java
@@ -0,0 +1,81 @@
+package org.grails.plugin.platform.events.push;
+
+import grails.events.GrailsEventsAware;
+import org.atmosphere.cpr.AtmosphereResourceEvent;
+import org.atmosphere.websocket.WebSocketEventListener;
+import org.grails.plugin.platform.events.Events;
+import org.grails.plugin.platform.events.publisher.EventsPublisher;
+
+/**
+ * Author: smaldini
+ * Date: 1/15/13
+ * Project: events-push
+ */
+public class BridgeWSListener implements WebSocketEventListener, GrailsEventsAware {
+
+ private Events grailsEvents;
+
+ public void setGrailsEvents(Events events) {
+ this.grailsEvents = events;
+ }
+
+ @Override
+ public void onHandshake(WebSocketEvent event) {
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, "onHandshake", event);
+ }
+
+ @Override
+ public void onMessage(WebSocketEvent event) {
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, "onMessage", event);
+ }
+
+ @Override
+ public void onClose(WebSocketEvent event) {
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, "onClose", event);
+ }
+
+ @Override
+ public void onControl(WebSocketEvent event) {
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, "onControl", event);
+ }
+
+ @Override
+ public void onDisconnect(WebSocketEvent event) {
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, "onDisconnect", event);
+ }
+
+ @Override
+ public void onConnect(WebSocketEvent event) {
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, "onConnect", event);
+ }
+
+ @Override
+ public void onPreSuspend(AtmosphereResourceEvent event) {
+ //grailsEvents.event(SharedConstants.PUSH_SCOPE, "onPreSuspend", event);
+ }
+
+ @Override
+ public void onSuspend(AtmosphereResourceEvent event) {
+ //grailsEvents.event(SharedConstants.PUSH_SCOPE, "onConnect", event);
+ }
+
+ @Override
+ public void onResume(AtmosphereResourceEvent event) {
+ //grailsEvents.event(SharedConstants.PUSH_SCOPE, "onResume", event);
+ }
+
+ @Override
+ public void onDisconnect(AtmosphereResourceEvent event) {
+ //grailsEvents.event(SharedConstants.PUSH_SCOPE, "onDisconnect", event);
+ }
+
+ @Override
+ public void onBroadcast(AtmosphereResourceEvent event) {
+ //grailsEvents.event(SharedConstants.PUSH_SCOPE, "onBroadcast", event);
+ }
+
+ @Override
+ public void onThrowable(AtmosphereResourceEvent event) {
+ //grailsEvents.event(SharedConstants.PUSH_SCOPE, "onThrowable", event);
+ }
+}
View
53 src/java/org/grails/plugin/platform/events/push/EventsPushHandler.java
@@ -30,6 +30,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import grails.events.GrailsEventsAware;
import groovy.json.JsonSlurper;
import groovy.lang.Closure;
import org.apache.commons.io.IOUtils;
@@ -67,15 +68,15 @@
private EventsRegistry eventsRegistry;
private BroadcasterFactory broadcasterFactory;
- public static final String ID_GRAILSEVENTS = "grailsEvents";
- public static final String ID_GRAILSEVENTSREGISTRY = "grailsEventsRegistry";
+ public static final String CONFIG_BRIDGE = "events.push.listener.bridge";
public static final String TOPICS_HEADER = "topics";
public static final String GLOBAL_TOPIC = "eventsbus";
- public static final String PUSH_SCOPE = "browser";
public static final String CLIENT_BROADCAST_PARAM = "browser";
public static final String CLIENT_FILTER_PARAM = "browserFilter";
public static final String DELIMITER = "<@>";
+ private AtmosphereResourceEventListener bridgeListener = null;
+
public HashMap<String, EventDefinition> broadcastersWhiteList = new HashMap<String, EventDefinition>();
private static final Method broadcastEventMethod = ReflectionUtils.findMethod(BroadcastEventWrapper.class, "broadcastEvent", EventMessage.class);
@@ -86,6 +87,7 @@ public void init() throws ServletException {
broadcasterFactory = BroadcasterFactory.getDefault();
ApplicationContext applicationContext = null;
+ GrailsApplication grailsApplication = null;
try {
applicationContext =
((ApplicationContext) getServletContext().getAttribute(ApplicationAttributes.APPLICATION_CONTEXT));
@@ -95,8 +97,9 @@ public void init() throws ServletException {
if (applicationContext != null) {
try {
- grailsEvents = applicationContext.getBean(ID_GRAILSEVENTS, EventsImpl.class);
- eventsRegistry = applicationContext.getBean(ID_GRAILSEVENTSREGISTRY, EventsRegistry.class);
+ grailsEvents = applicationContext.getBean(EventsImpl.class);
+ eventsRegistry = applicationContext.getBean(EventsRegistry.class);
+ grailsApplication = applicationContext.getBean(GrailsApplication.class);
} catch (Exception c) {
log.error("Couldn't manage to retrieve beans", c);
}
@@ -145,12 +148,47 @@ public BroadcastAction filter(Object originalMessage, Object message) {
return new BroadcastAction(message);
}
});
+
broadcastersWhiteList.putAll(registerTopics(eventsRegistry, grailsEvents));
+
+ defineBridgeListener(grailsApplication, grailsEvents);
+
b.scheduleFixedBroadcast(2+DELIMITER+"{}", 10, TimeUnit.SECONDS);
}
}
+ protected void defineBridgeListener(GrailsApplication application, Events grailsEvents){
+ Object bridgeConfig = application.getConfig().flatten().get(CONFIG_BRIDGE);
+
+ if(bridgeConfig == null)
+ return;
+
+ if(Boolean.class.isAssignableFrom(bridgeConfig.getClass()) && (Boolean)bridgeConfig){
+ bridgeListener = new BridgeWSListener();
+ }else if(Class.class.isAssignableFrom(bridgeConfig.getClass())
+ && AtmosphereResourceEventListener.class.isAssignableFrom(((Class)bridgeConfig))){
+ try {
+ bridgeListener = (AtmosphereResourceEventListener)((Class)bridgeConfig).newInstance();
+ } catch (InstantiationException e) {
+ log.error("Failed to create listener", e);
+ } catch (IllegalAccessException e) {
+ log.error("Failed to find constructor for bridge listener",e);
+ }
+ }
+
+ if(bridgeListener != null){
+ log.info("Bridge listener created, all browsers events will be dispatched to "+bridgeListener.toString());
+
+ if(GrailsEventsAware.class.isAssignableFrom(bridgeListener.getClass())){
+ ((GrailsEventsAware)bridgeListener).setGrailsEvents(grailsEvents);
+ log.debug("Platform-core Events are successfully bridged to "+bridgeListener.toString());
+ }
+ }
+
+
+ }
+
static public Map<String, EventDefinition> registerTopics(EventsRegistry eventsRegistry, Events grailsEvents) {
Map<String, EventDefinition> doneTopics = new HashMap<String, EventDefinition>();
Object broadcastClient;
@@ -220,6 +258,9 @@ public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOExce
m.addListener(new AtmosphereResourceEventListenerAdapter());
}
+ if (bridgeListener != null)
+ m.addListener(bridgeListener);
+
m.setBroadcaster(defaultBroadcaster);
if (header != null && header.equalsIgnoreCase(HeaderConfig.LONG_POLLING_TRANSPORT)) {
@@ -259,7 +300,7 @@ public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOExc
return;
}
final Object body = element.containsKey("body") ? element.get("body") : null;
- grailsEvents.event(PUSH_SCOPE, topic, body != null ? body : element);
+ grailsEvents.event(SharedConstants.PUSH_SCOPE, topic, body != null ? body : element);
}
// private String extractTopic(String pathInfo) {
View
10 src/java/org/grails/plugin/platform/events/push/SharedConstants.java
@@ -0,0 +1,10 @@
+package org.grails.plugin.platform.events.push;
+
+/**
+ * Author: smaldini
+ * Date: 1/15/13
+ * Project: events-push
+ */
+public class SharedConstants {
+ public static final String PUSH_SCOPE = "browser";
+}
Please sign in to comment.
Something went wrong with that request. Please try again.