Event management
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 4 May 2009 20:42:23 +0000 (20:42 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 4 May 2009 20:42:23 +0000 (20:42 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@2396 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

29 files changed:
demo/pom.xml
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/EventPublisherAspect.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/AddEventListenerController.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/PollEventController.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/RemoveEventListenerController.java [new file with mode: 0644]
runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAgent.java
runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAgentProxy.java
runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcEventListener.java [new file with mode: 0644]
runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcEventPublisher.java [new file with mode: 0644]
runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsTransferNewExecution.java
runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/MarshallerMessageConverter.java
runtime/org.argeo.slc.support.activemq/src/main/resources/org/argeo/slc/activemq/destinations.xml
runtime/org.argeo.slc.support.activemq/src/main/resources/org/argeo/slc/activemq/spring-agent.xml [deleted file]
runtime/org.argeo.slc.support.castor/pom.xml
runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg.xml
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/runtime/AbstractAgent.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEvent.java [new file with mode: 0644]
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListener.java [new file with mode: 0644]
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListenerDescriptor.java [new file with mode: 0644]
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListenerRegister.java [new file with mode: 0644]
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventPublisher.java [new file with mode: 0644]
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.jms/META-INF/MANIFEST.MF
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.jms/META-INF/spring/jms-osgi.xml
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.jms/META-INF/spring/jms.xml
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.services/META-INF/spring/services-osgi.xml
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.services/META-INF/spring/services.xml
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.webapp.war/META-INF/MANIFEST.MF
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.webapp.war/WEB-INF/osgi.xml
server/org.argeo.slc.siteserver/bundles/org.argeo.slc.webapp.war/WEB-INF/slc-service-servlet.xml

index f2d0b19e9950939c0c6c13f411627fc8707fbaac..c7df955a207ba0e03c05947bbeaa21b15be90800 100644 (file)
@@ -20,6 +20,9 @@
                                <groupId>org.argeo.slc.maven</groupId>
                                <artifactId>maven-argeo-osgi-plugin</artifactId>
                                <configuration>
+                                       <argsToAppend>
+                                               <arg>-clean</arg>
+                                       </argsToAppend>
                                        <systemProperties>
                                                <slc.osgi.bundles>${basedir}/site;in=*;ex=**/.svn/**,${basedir}/../server/org.argeo.slc.siteserver/bundles;in=*;ex=**/.svn/**</slc.osgi.bundles>
                                        </systemProperties>
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/EventPublisherAspect.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/EventPublisherAspect.java
new file mode 100644 (file)
index 0000000..ea0ce12
--- /dev/null
@@ -0,0 +1,57 @@
+package org.argeo.slc.services;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.core.runtime.AbstractAgent;
+import org.argeo.slc.msg.event.SlcEvent;
+import org.argeo.slc.msg.event.SlcEventPublisher;
+import org.argeo.slc.runtime.SlcAgentDescriptor;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+
+@Aspect
+public class EventPublisherAspect {
+       private final static Log log = LogFactory
+                       .getLog(EventPublisherAspect.class);
+
+       private List<SlcEventPublisher> eventPublishers;
+
+       @After("execution(void org.argeo.slc.services.runtime.AgentService.register(..))")
+       public void registerAgent(JoinPoint jp) throws Throwable {
+               SlcAgentDescriptor agentDescriptor = (SlcAgentDescriptor) jp.getArgs()[0];
+               SlcEvent event = new SlcEvent("agentRegistered");
+               event.getHeaders().put(AbstractAgent.PROPERTY_SLC_AGENT_ID,
+                               agentDescriptor.getUuid());
+               publishEvent(event);
+       }
+
+       @After("execution(void org.argeo.slc.services.runtime.AgentService.unregister(..))")
+       public void unregisterAgent(JoinPoint jp) throws Throwable {
+               SlcAgentDescriptor agentDescriptor = (SlcAgentDescriptor) jp.getArgs()[0];
+               SlcEvent event = new SlcEvent("agentUnregistered");
+               event.getHeaders().put(AbstractAgent.PROPERTY_SLC_AGENT_ID,
+                               agentDescriptor.getUuid());
+               publishEvent(event);
+       }
+
+       public void setEventPublishers(List<SlcEventPublisher> eventPublishers) {
+               this.eventPublishers = eventPublishers;
+       }
+
+       protected void publishEvent(SlcEvent event) {
+
+               for (Iterator<SlcEventPublisher> it = eventPublishers.iterator(); it
+                               .hasNext();) {
+                       SlcEventPublisher eventPublisher = it.next();
+                       if (log.isTraceEnabled())
+                               log.debug("Publish event: "
+                                               + event.getHeaders().get(SlcEvent.EVENT_TYPE) + " to "
+                                               + eventPublisher);
+                       eventPublisher.publish(event);
+               }
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/AddEventListenerController.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/AddEventListenerController.java
new file mode 100644 (file)
index 0000000..d72d53b
--- /dev/null
@@ -0,0 +1,33 @@
+package org.argeo.slc.web.mvc.event;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.slc.msg.event.SlcEvent;
+import org.argeo.slc.msg.event.SlcEventListenerDescriptor;
+import org.argeo.slc.msg.event.SlcEventListenerRegister;
+import org.argeo.slc.web.mvc.AbstractServiceController;
+import org.springframework.web.servlet.ModelAndView;
+
+public class AddEventListenerController extends AbstractServiceController {
+
+       private SlcEventListenerRegister eventListenerRegister;
+
+       @Override
+       protected void handleServiceRequest(HttpServletRequest request,
+                       HttpServletResponse response, ModelAndView modelAndView)
+                       throws Exception {
+               String eventType = request.getParameter(SlcEvent.EVENT_TYPE);
+               String eventFilter = request.getParameter(SlcEvent.EVENT_FILTER);
+
+               eventListenerRegister
+                               .addEventListenerDescriptor(new SlcEventListenerDescriptor(
+                                               eventType, eventFilter));
+       }
+
+       public void setEventListenerRegister(
+                       SlcEventListenerRegister eventListenerRegister) {
+               this.eventListenerRegister = eventListenerRegister;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/PollEventController.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/PollEventController.java
new file mode 100644 (file)
index 0000000..0ebb2f6
--- /dev/null
@@ -0,0 +1,56 @@
+package org.argeo.slc.web.mvc.event;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.msg.event.SlcEvent;
+import org.argeo.slc.msg.event.SlcEventListener;
+import org.argeo.slc.msg.event.SlcEventListenerRegister;
+import org.argeo.slc.web.mvc.AbstractServiceController;
+import org.springframework.web.servlet.ModelAndView;
+
+public class PollEventController extends AbstractServiceController {
+       private final static Log log = LogFactory.getLog(PollEventController.class);
+
+       private SlcEventListener eventListener;
+       private SlcEventListenerRegister eventListenerRegister;
+       private Long defaultTimeout = 10000l;
+
+       @Override
+       protected void handleServiceRequest(HttpServletRequest request,
+                       HttpServletResponse response, ModelAndView modelAndView)
+                       throws Exception {
+               String timeoutStr = request.getParameter("timeout");
+
+               final Long timeout;
+               if (timeoutStr != null)
+                       timeout = Long.parseLong(timeoutStr);
+               else
+                       timeout = defaultTimeout;
+
+               SlcEvent event = eventListener.listen(eventListenerRegister, timeout);
+               if (event != null) {
+                       modelAndView.addObject("event", event);
+
+                       if (log.isTraceEnabled())
+                               log.debug("Received event: "
+                                               + event.getHeaders().get(SlcEvent.EVENT_TYPE));
+               }
+       }
+
+       public void setEventListener(SlcEventListener slcEventListener) {
+               this.eventListener = slcEventListener;
+       }
+
+       public void setEventListenerRegister(
+                       SlcEventListenerRegister eventListenerRegister) {
+               this.eventListenerRegister = eventListenerRegister;
+       }
+
+       public void setDefaultTimeout(Long defaultTimeout) {
+               this.defaultTimeout = defaultTimeout;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/RemoveEventListenerController.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/event/RemoveEventListenerController.java
new file mode 100644 (file)
index 0000000..4d9f362
--- /dev/null
@@ -0,0 +1,33 @@
+package org.argeo.slc.web.mvc.event;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.slc.msg.event.SlcEvent;
+import org.argeo.slc.msg.event.SlcEventListenerDescriptor;
+import org.argeo.slc.msg.event.SlcEventListenerRegister;
+import org.argeo.slc.web.mvc.AbstractServiceController;
+import org.springframework.web.servlet.ModelAndView;
+
+public class RemoveEventListenerController extends AbstractServiceController {
+
+       private SlcEventListenerRegister eventListenerRegister;
+
+       @Override
+       protected void handleServiceRequest(HttpServletRequest request,
+                       HttpServletResponse response, ModelAndView modelAndView)
+                       throws Exception {
+               String eventType = request.getParameter(SlcEvent.EVENT_TYPE);
+               String eventFilter = request.getParameter(SlcEvent.EVENT_FILTER);
+
+               eventListenerRegister
+                               .removeEventListenerDescriptor(new SlcEventListenerDescriptor(
+                                               eventType, eventFilter));
+       }
+
+       public void setEventListenerRegister(
+                       SlcEventListenerRegister eventListenerRegister) {
+               this.eventListenerRegister = eventListenerRegister;
+       }
+
+}
index e7899d1ae0500e72186e4155a4ca9f9338e0d633..85bdb1451dab344d6f10e9053126758bad29f667 100644 (file)
@@ -32,8 +32,6 @@ import org.springframework.jms.core.MessagePostProcessor;
 public class JmsAgent extends AbstractAgent implements SlcAgent,
                InitializingBean, DisposableBean, MessageListener {
        public final static String PROPERTY_QUERY = "query";
-       public final static String PROPERTY_SLC_AGENT_ID = "slc_agentId";
-
        public final static String QUERY_PING_ALL = "pingAll";
 
        private final static Log log = LogFactory.getLog(JmsAgent.class);
@@ -159,7 +157,7 @@ public class JmsAgent extends AbstractAgent implements SlcAgent,
                                        public Message postProcessMessage(Message messageToSend)
                                                        throws JMSException {
                                                messageToSend.setStringProperty(PROPERTY_QUERY, query);
-                                               messageToSend.setStringProperty(PROPERTY_SLC_AGENT_ID,
+                                               messageToSend.setStringProperty(AbstractAgent.PROPERTY_SLC_AGENT_ID,
                                                                agentDescriptor.getUuid());
                                                messageToSend.setJMSCorrelationID(correlationId);
                                                return messageToSend;
index 4029af0a9a95619bff92fdfa788fa85c74803952..7fa270a9b90096238399da38a87c62c124275d54 100644 (file)
@@ -12,6 +12,7 @@ import javax.jms.TextMessage;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.core.runtime.AbstractAgent;
 import org.argeo.slc.execution.ExecutionModuleDescriptor;
 import org.argeo.slc.msg.ExecutionAnswer;
 import org.argeo.slc.process.SlcExecution;
@@ -175,7 +176,7 @@ public class JmsAgentProxy implements SlcAgent {
                                msg = session.createTextMessage();
                        else
                                msg = toMessage(body, session);
-                       msg.setStringProperty(JmsAgent.PROPERTY_SLC_AGENT_ID, agentUuid);
+                       msg.setStringProperty(AbstractAgent.PROPERTY_SLC_AGENT_ID, agentUuid);
                        msg.setStringProperty(JmsAgent.PROPERTY_QUERY, query);
                        msg.setJMSCorrelationID(correlationId);
                        setArguments(msg);
diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcEventListener.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcEventListener.java
new file mode 100644 (file)
index 0000000..a05a367
--- /dev/null
@@ -0,0 +1,94 @@
+package org.argeo.slc.jms;
+
+import java.util.List;
+
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.msg.event.SlcEvent;
+import org.argeo.slc.msg.event.SlcEventListener;
+import org.argeo.slc.msg.event.SlcEventListenerDescriptor;
+import org.argeo.slc.msg.event.SlcEventListenerRegister;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.support.converter.MessageConverter;
+
+public class JmsSlcEventListener implements SlcEventListener {
+       private final static Log log = LogFactory.getLog(JmsSlcEventListener.class);
+
+       private Destination eventsDestination;
+       private ConnectionFactory jmsConnectionFactory;
+       private MessageConverter messageConverter;
+
+       public SlcEvent listen(SlcEventListenerRegister register, Long timeout) {
+               JmsTemplate jmsTemplate = new JmsTemplate(jmsConnectionFactory);
+               jmsTemplate.setMessageConverter(messageConverter);
+               jmsTemplate.setReceiveTimeout(timeout);
+
+               List<SlcEventListenerDescriptor> descriptors = register
+                               .getDescriptorsCopy();
+
+               if (descriptors.size() == 0) {
+                       // No listeners, just waiting
+                       try {
+                               Thread.sleep(timeout);
+                       } catch (InterruptedException e) {
+                               // silent
+                       }
+                       return null;
+               } else {
+                       String selector = createSelector(descriptors);
+
+                       if (log.isTraceEnabled())
+                               log.debug("Selector: " + selector);
+
+                       Object obj = jmsTemplate.receiveSelectedAndConvert(
+                                       eventsDestination, selector);
+
+                       if (obj == null)
+                               return null;
+                       else
+                               return (SlcEvent) obj;
+               }
+       }
+
+       /** Returns null if no filter */
+       protected String createSelector(List<SlcEventListenerDescriptor> descriptors) {
+               if (descriptors.size() == 0)
+                       throw new SlcException("No listeners, cannot generate JMS selector");
+
+               StringBuffer buf = new StringBuffer(256);
+               Boolean first = true;
+               for (SlcEventListenerDescriptor descriptor : descriptors) {
+                       if (first)
+                               first = false;
+                       else
+                               buf.append(" OR ");
+
+                       buf.append('(');
+                       buf.append(SlcEvent.EVENT_TYPE).append("=").append('\'').append(
+                                       descriptor.getEventType()).append('\'');
+                       if (descriptor.getFilter() != null) {
+                               buf.append(" AND ");
+                               buf.append('(').append(descriptor.getFilter()).append(')');
+                       }
+                       buf.append(')');
+               }
+               return buf.toString();
+       }
+
+       public void setEventsDestination(Destination eventsDestination) {
+               this.eventsDestination = eventsDestination;
+       }
+
+       public void setJmsConnectionFactory(ConnectionFactory jmsConnectionFactory) {
+               this.jmsConnectionFactory = jmsConnectionFactory;
+       }
+
+       public void setMessageConverter(MessageConverter messageConverter) {
+               this.messageConverter = messageConverter;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcEventPublisher.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcEventPublisher.java
new file mode 100644 (file)
index 0000000..bcf1332
--- /dev/null
@@ -0,0 +1,52 @@
+package org.argeo.slc.jms;
+
+import java.util.Map;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import org.argeo.slc.msg.event.SlcEvent;
+import org.argeo.slc.msg.event.SlcEventPublisher;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessagePostProcessor;
+
+public class JmsSlcEventPublisher implements SlcEventPublisher {
+       private Destination eventsDestination;
+       private JmsTemplate jmsTemplate;
+
+       public void publish(final SlcEvent event) {
+               jmsTemplate.convertAndSend(eventsDestination, event,
+                               new MessagePostProcessor() {
+
+                                       public Message postProcessMessage(Message message)
+                                                       throws JMSException {
+                                               Map<String, String> headers = event.getHeaders();
+                                               for (String key : headers.keySet()) {
+                                                       message.setStringProperty(key, headers.get(key));
+                                               }
+                                               return message;
+                                       }
+                               });
+               // jmsTemplate.send(eventsDestination, new MessageCreator() {
+               // public Message createMessage(Session session) throws JMSException {
+               // TextMessage msg = session.createTextMessage();
+               // // TODO: remove workaround when upgrading to ActiveMQ 5.3
+               // // Workaround for
+               // // https://issues.apache.org/activemq/browse/AMQ-2046
+               // msg.setText("");
+               //
+               // return msg;
+               // }
+               // });
+       }
+
+       public void setEventsDestination(Destination eventsDestination) {
+               this.eventsDestination = eventsDestination;
+       }
+
+       public void setJmsTemplate(JmsTemplate jmsTemplate) {
+               this.jmsTemplate = jmsTemplate;
+       }
+
+}
index 74f1eb2318c26cc64c3ac4835fed94d6a697aa5f..68295e8cf14dd0d3bbcfaf10acc8301d168b0ff4 100644 (file)
@@ -4,6 +4,7 @@ import javax.jms.Message;
 import javax.jms.MessageListener;
 
 import org.argeo.slc.SlcException;
+import org.argeo.slc.core.runtime.AbstractAgent;
 import org.argeo.slc.msg.MsgHandler;
 import org.argeo.slc.process.SlcExecution;
 import org.argeo.slc.runtime.SlcAgent;
@@ -19,7 +20,7 @@ public class JmsTransferNewExecution implements MessageListener {
        public void onMessage(final Message message) {
                try {
                        String agentId = message
-                                       .getStringProperty(JmsAgent.PROPERTY_SLC_AGENT_ID);
+                                       .getStringProperty(AbstractAgent.PROPERTY_SLC_AGENT_ID);
                        final SlcAgent agent = agentFactory.getAgent(agentId);
                        final SlcExecution slcExecution = (SlcExecution) messageConverter
                                        .fromMessage(message);
index b42602606ea5f834e76d6514a7151e7078695e71..31e6354452a6465987879062daae8586270c5561 100644 (file)
@@ -24,8 +24,13 @@ public class MarshallerMessageConverter implements MessageConverter {
        private Marshaller marshaller;
        private Unmarshaller unmarshaller;
 
+       /** @return the converted message or null if the message itself is null */
        public Object fromMessage(Message message) throws JMSException,
                        MessageConversionException {
+               if (message == null) {
+                       return null;
+               }
+
                if (log.isTraceEnabled()) {
                        Enumeration<String> names = message.getPropertyNames();
                        while (names.hasMoreElements()) {
@@ -38,6 +43,11 @@ public class MarshallerMessageConverter implements MessageConverter {
                if (message instanceof TextMessage) {
 
                        String text = ((TextMessage) message).getText();
+
+                       if (text == null)
+                               throw new SlcException(
+                                               "Cannot unmarshall message without body: " + message);
+
                        try {
                                return unmarshaller.unmarshal(new StringSource(text));
                        } catch (Exception e) {
index eb84e02b007b1e4b58137693457387518676146a..967b0daf9993e624eff055597bedb07c1e21cb9f 100644 (file)
@@ -4,8 +4,10 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
        default-lazy-init="false">
 
-       <!-- Destinations -->
-
+       <!-- Events -->
+       <bean id="slcJms.destination.events" p:physicalName="events"
+               parent="slcJms.amTopic" />
+       
        <!-- Agent service -->
        <bean id="slcJms.destination.agent.register" p:physicalName="agent.register"
                parent="slcJms.amTopic" />
diff --git a/runtime/org.argeo.slc.support.activemq/src/main/resources/org/argeo/slc/activemq/spring-agent.xml b/runtime/org.argeo.slc.support.activemq/src/main/resources/org/argeo/slc/activemq/spring-agent.xml
deleted file mode 100644 (file)
index a6492a5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-       http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"
-       default-lazy-init="false">
-
-       <import resource="classpath:org/argeo/slc/activemq/spring.xml" />
-
-       <bean id="slcDefault.jms.agent" class="org.argeo.slc.jms.JmsAgent"
-               autowire="byType">
-               <property name="jmsTemplate" ref="slcDefault.jms.jmsTemplateCastor" />
-               <property name="agentRegister" ref="slcJms.destination.agent.register" />
-               <property name="agentUnregister" ref="slcJms.destination.agent.unregister" />
-       </bean>
-
-       <!-- Templates -->
-       <bean id="slcDefault.jms.listener.newExecution" parent="slcTemplate.jms.listenerContainer">
-               <property name="connectionFactory" ref="slcDefault.jms.connectionFactory" />
-               <property name="destination" ref="slcJms.destination.agent.newExecution" />
-               <property name="messageListener">
-                       <bean parent="slcTemplate.jms.listenerAdapterCastor">
-                               <constructor-arg ref="slcDefault.jms.agent" />
-                               <property name="defaultListenerMethod" value="newExecution" />
-                       </bean>
-               </property>
-               <property name="messageSelector">
-                       <bean factory-bean="slcDefault.jms.agent" factory-method="getMessageSelector"/>
-               </property>
-       </bean>
-
-</beans>
\ No newline at end of file
index 5fa3b3f9aab37d8d5b5fba37e44830f10f63fda8..945dc6ec026111cf74682739024428c419254918 100644 (file)
@@ -47,6 +47,7 @@
                                                        org.argeo.slc.core.execution;resolution:=optional,
                                                        org.argeo.slc.msg;resolution:=optional,
                                                        org.argeo.slc.msg.process;resolution:=optional,
+                                                       org.argeo.slc.msg.event;resolution:=optional,
                                                        org.argeo.slc.msg.test.tree;resolution:=optional,
                                                        org.argeo.slc.detached;resolution:=optional,
                                                        org.apache.xml.serialize
index 1d13dee7d608c324f6463e4b0cb38d0ccc741d22..146c020e8ae9c012b0b4046b66db5ec03e422dea 100644 (file)
                <field name="slcExecution" type="org.argeo.slc.process.SlcExecution" />
        </class>
 
+       <!-- EVENTS -->
+
+       <class name="org.argeo.slc.msg.event.SlcEvent">
+               <map-to ns-uri="http://argeo.org/projects/slc/schemas"
+                       ns-prefix="slc" />
+               <field name="headers" collection="map">
+                       <bind-xml name="header" location="headers">
+                               <class name="org.exolab.castor.mapping.MapItem">
+                                       <map-to ns-uri="http://argeo.org/projects/slc/schemas"
+                                               ns-prefix="slc" />
+                                       <field name="key" type="string">
+                                               <bind-xml name="name" node="attribute" />
+                                       </field>
+                                       <field name="value" type="string">
+                                               <bind-xml node="text" />
+                                       </field>
+                               </class>
+                       </bind-xml>
+               </field>
+       </class>
 
 </mapping>
\ No newline at end of file
index c7a419c655cb2dc52476128ae9c8349d30471971..16f87e9a3755ae8e86b15cf38f824ceeda7141c0 100644 (file)
@@ -7,6 +7,7 @@ public abstract class AbstractAgent {
 //     private final static Log log = LogFactory.getLog(AbstractAgent.class);
 
        private ExecutionModulesManager modulesManager;
+       public final static String PROPERTY_SLC_AGENT_ID = "slc_agentId";
 
        public void runSlcExecution(final SlcExecution slcExecution) {
                modulesManager.process(slcExecution);
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEvent.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEvent.java
new file mode 100644 (file)
index 0000000..695ec24
--- /dev/null
@@ -0,0 +1,27 @@
+package org.argeo.slc.msg.event;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SlcEvent {
+       public final static String EVENT_TYPE = "slc_eventType";
+       public final static String EVENT_FILTER = "slc_eventFilter";
+
+       private Map<String, String> headers = new HashMap<String, String>();
+
+       public SlcEvent() {
+       }
+
+       public SlcEvent(String eventType) {
+               headers.put(EVENT_TYPE, eventType);
+       }
+
+       public Map<String, String> getHeaders() {
+               return headers;
+       }
+
+       public void setHeaders(Map<String, String> headers) {
+               this.headers = headers;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListener.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListener.java
new file mode 100644 (file)
index 0000000..75048f7
--- /dev/null
@@ -0,0 +1,11 @@
+package org.argeo.slc.msg.event;
+
+public interface SlcEventListener {
+       /**
+        * Blocks until an event is received or timeout is reached
+        * 
+        * @return the event received or null if timeout was reached before
+        *         receiving one
+        */
+       public SlcEvent listen(SlcEventListenerRegister register, Long timeout);
+}
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListenerDescriptor.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListenerDescriptor.java
new file mode 100644 (file)
index 0000000..f3b7c5d
--- /dev/null
@@ -0,0 +1,35 @@
+package org.argeo.slc.msg.event;
+
+import java.io.Serializable;
+
+public class SlcEventListenerDescriptor implements Serializable {
+       static final long serialVersionUID = 1l;
+
+       private final String eventType;
+       private final String filter;
+
+       public SlcEventListenerDescriptor(String eventType, String filter) {
+               super();
+               this.eventType = eventType;
+               this.filter = filter;
+       }
+
+       public String getEventType() {
+               return eventType;
+       }
+
+       public String getFilter() {
+               return filter;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (obj instanceof SlcEventListenerDescriptor) {
+                       SlcEventListenerDescriptor eventListenerDescriptor = (SlcEventListenerDescriptor) obj;
+                       return eventListenerDescriptor.getEventType()
+                                       .equals(getEventType());
+               }
+               return false;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListenerRegister.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventListenerRegister.java
new file mode 100644 (file)
index 0000000..52aa8c3
--- /dev/null
@@ -0,0 +1,29 @@
+package org.argeo.slc.msg.event;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+public class SlcEventListenerRegister implements Serializable {
+       static final long serialVersionUID = 1l;
+
+       /** Synchronized */
+       private List<SlcEventListenerDescriptor> descriptors = new Vector<SlcEventListenerDescriptor>();
+
+       public synchronized void addEventListenerDescriptor(
+                       SlcEventListenerDescriptor eventListenerDescriptor) {
+               if (descriptors.contains(eventListenerDescriptor))
+                       descriptors.remove(eventListenerDescriptor);
+               descriptors.add(eventListenerDescriptor);
+       }
+
+       public synchronized void removeEventListenerDescriptor(
+                       SlcEventListenerDescriptor eventListenerDescriptor) {
+               descriptors.remove(eventListenerDescriptor);
+       }
+
+       public synchronized List<SlcEventListenerDescriptor> getDescriptorsCopy() {
+               return new ArrayList<SlcEventListenerDescriptor>(descriptors);
+       }
+}
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventPublisher.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/event/SlcEventPublisher.java
new file mode 100644 (file)
index 0000000..d7ab830
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.slc.msg.event;
+
+public interface SlcEventPublisher {
+       public void publish(SlcEvent event);
+}
index 1a263df56758cc774eeb24f00afeead894e9cb49..58fb3ea785433e901906ca0010be3f95e15367f0 100644 (file)
@@ -7,6 +7,7 @@ Import-Package: javax.jms,
 Require-Bundle: 
  org.argeo.slc.specs,
  org.argeo.slc.server,
+ org.argeo.slc.support.simple,
  org.argeo.slc.support.activemq,
  org.springframework.core,
  org.springframework.context,
index d644211cfb6741a65e4e9d0b99c1aa6f3db8b2c6..6ba1c5c42678dc4ca43092f3022a61ed8fa6d26e 100644 (file)
@@ -18,4 +18,7 @@
                bean-name="jmsTransactionManager" />
 
        <reference id="agentFactory" interface="org.argeo.slc.runtime.SlcAgentFactory" />
+
+       <service ref="jmsEventListener" interface="org.argeo.slc.msg.event.SlcEventListener" />
+       <service ref="jmsEventPublisher" interface="org.argeo.slc.msg.event.SlcEventPublisher" />
 </beans:beans>
\ No newline at end of file
index d747ec676669483a0b8cdecfd1fa43c5dba9ff54..d141b7f8799e7a1e9fa29808f97fe18de083fc5f 100644 (file)
@@ -6,6 +6,18 @@
 
        <import resource="classpath:org/argeo/slc/activemq/spring.xml" />
 
+       <!-- Events -->
+       <bean id="jmsEventListener" class="org.argeo.slc.jms.JmsSlcEventListener">
+               <property name="jmsConnectionFactory" ref="jmsConnectionFactory" />
+               <property name="eventsDestination" ref="slcJms.destination.events" />
+               <property name="messageConverter" ref="slcDefault.jms.castorMessageConverter" />
+       </bean>
+
+       <bean id="jmsEventPublisher" class="org.argeo.slc.jms.JmsSlcEventPublisher">
+               <property name="jmsTemplate" ref="jmsTemplate" />
+               <property name="eventsDestination" ref="slcJms.destination.events" />
+       </bean>
+
        <!-- Agent Service -->
        <bean id="agentService.jmsContainer.register" parent="listenerContainer">
                <property name="destination" ref="slcJms.destination.agent.register" />
                </property> </bean>
        -->
 
+       <!-- Common -->
+       <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
+               <property name="messageConverter" ref="slcDefault.jms.castorMessageConverter" />
+               <property name="connectionFactory" ref="jmsConnectionFactory" />
+       </bean>
+
        <!-- Templates -->
        <bean id="listenerContainer"
                class="org.springframework.jms.listener.DefaultMessageListenerContainer"
index f486d9dee08c29cea8b3274f4ea21bae20f4f3c5..a078000b826672b3b5e97913e0e12e418a797495 100644 (file)
@@ -30,4 +30,7 @@
 
        <reference id="agentFactory" interface="org.argeo.slc.runtime.SlcAgentFactory" />
 
+       <list id="eventPublishers" interface="org.argeo.slc.msg.event.SlcEventPublisher"
+               cardinality="0..N" />
+
 </beans:beans>
\ No newline at end of file
index 45406600f7a26e98ec361aed3a154b36d951d0c4..6f4602a261027491915d55057bd9dbe1f1a6381f 100644 (file)
                </property>
        </bean>
 
+       <!-- Events -->
+       <aop:aspectj-autoproxy />
+
+       <bean id="eventPublisherAspect" class="org.argeo.slc.services.EventPublisherAspect">
+               <property name="eventPublishers" ref="eventPublishers" />
+       </bean>
+
        <!-- Services -->
        <bean id="testManagerService" class="org.argeo.slc.services.impl.test.TestManagerServiceImpl">
                <constructor-arg ref="testResultDao" />
index 9ba6c5a942ebead58eabc83585b852c32cdb7d1b..8e1837520053cd297f6d668ee5b4023e0fe1a9e1 100644 (file)
@@ -23,12 +23,18 @@ Import-Package: com.sun.xml.messaging.saaj.soap;optional=true,
  org.hibernate.jdbc,
  org.springframework.aop,
  org.springframework.aop.framework,
+ org.springframework.aop.scope,
+ net.sf.cglib.proxy,
+ net.sf.cglib.core,
+ net.sf.cglib.reflect,
  org.springframework.orm.hibernate3.support,
  org.springframework.osgi.web.context.support,
  org.springframework.oxm.castor,
  org.springframework.transaction,
+ org.springframework.beans.factory.support,
  org.springframework.web.context,
  org.springframework.web.context.support,
+ org.springframework.web.context.request,
  org.springframework.web.servlet,
  org.springframework.web.servlet.handler,
  org.springframework.web.servlet.view,
index 28612127b30a291136e4a157f15f41f953c1304f..461f8896387ef93a840cec18ed87af0ce97f9a46 100644 (file)
@@ -33,4 +33,6 @@
 \r
        <reference id="agentFactory" interface="org.argeo.slc.runtime.SlcAgentFactory" />\r
 \r
+       <reference id="eventListener" interface="org.argeo.slc.msg.event.SlcEventListener" />\r
+\r
 </beans:beans>
\ No newline at end of file
index 0f913c85f96a176325041df4c89bcb6a3a0c06b6..5f17ee8d234e5a4fb6a85d608a05739a71f22416 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
+       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 
        <import resource="classpath:/org/argeo/slc/castor/spring/applicationContext.xml" />
 
                <property name="agentFactory" ref="agentFactory" />
        </bean>
 
+       <!-- Events -->
+       <bean name="/addEventListener.service"
+               class="org.argeo.slc.web.mvc.event.AddEventListenerController">
+               <property name="eventListenerRegister" ref="eventListenerRegister" />
+       </bean>
+
+       <bean name="/removeEventListener.service"
+               class="org.argeo.slc.web.mvc.event.RemoveEventListenerController">
+               <property name="eventListenerRegister" ref="eventListenerRegister" />
+       </bean>
+
+       <bean name="/pollEvent.service" class="org.argeo.slc.web.mvc.event.PollEventController">
+               <property name="eventListenerRegister" ref="eventListenerRegister" />
+               <property name="eventListener" ref="eventListener" />
+       </bean>
+
+       <bean name="eventListenerRegister" class="org.argeo.slc.msg.event.SlcEventListenerRegister"
+               scope="session">
+               <aop:scoped-proxy />
+       </bean>
+
        <bean id="handlerMapping"
                class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
                <property name="interceptors">