You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2016/03/17 08:59:28 UTC

karaf git commit: [KARAF-4370] Add feature, do not use DS

Repository: karaf
Updated Branches:
  refs/heads/master 8aabfbd43 -> d315b32ee


[KARAF-4370] Add feature, do not use DS


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/d315b32e
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/d315b32e
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/d315b32e

Branch: refs/heads/master
Commit: d315b32eef5bc4b0b30c993f811136d73d558612
Parents: 8aabfbd
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Thu Mar 17 08:59:20 2016 +0100
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Mar 17 08:59:20 2016 +0100

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |  3 +-
 event/pom.xml                                   |  2 +-
 .../apache/karaf/event/EventDisplayCommand.java | 57 ---------------
 .../org/apache/karaf/event/EventPrinter.java    | 69 ------------------
 .../apache/karaf/event/EventSendCommand.java    | 64 -----------------
 .../apache/karaf/event/EventTailCommand.java    | 76 --------------------
 .../event/command/EventDisplayCommand.java      | 57 +++++++++++++++
 .../karaf/event/command/EventPrinter.java       | 69 ++++++++++++++++++
 .../karaf/event/command/EventSendCommand.java   | 64 +++++++++++++++++
 .../karaf/event/command/EventTailCommand.java   | 76 ++++++++++++++++++++
 .../apache/karaf/event/service/Activator.java   | 25 +++++++
 .../karaf/event/EventDisplayCommandTest.java    | 44 ------------
 .../apache/karaf/event/EventPrinterTest.java    | 70 ------------------
 .../karaf/event/EventSendCommandTest.java       | 55 --------------
 .../karaf/event/EventTailCommandTest.java       | 70 ------------------
 .../event/command/EventDisplayCommandTest.java  | 45 ++++++++++++
 .../karaf/event/command/EventPrinterTest.java   | 71 ++++++++++++++++++
 .../event/command/EventSendCommandTest.java     | 56 +++++++++++++++
 .../event/command/EventTailCommandTest.java     | 71 ++++++++++++++++++
 19 files changed, 537 insertions(+), 507 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 70520ea..8631019 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -499,6 +499,7 @@
         </config>
         <bundle start-level="5">mvn:org.apache.felix/org.apache.felix.metatype/${felix.metatype.version}</bundle>
         <bundle start-level="5">mvn:org.apache.karaf.services/org.apache.karaf.services.eventadmin/${project.version}</bundle>
+        <bundle>mvn:org.apache.karaf/org.apache.karaf.event/${project.version}</bundle>
         <conditional>
             <condition>webconsole</condition>
             <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/${felix.eventadmin.webconsole.plugin.version}</bundle>
@@ -573,7 +574,7 @@
         </config>
         <bundle>mvn:org.jolokia/jolokia-osgi/${jolokia.version}</bundle>
     </feature>
-
+    
     <feature name="standard" description="Wrap feature describing all features part of a standard distribution" version="${project.version}">
         <feature>wrap</feature>
         <feature>aries-blueprint</feature>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/pom.xml
----------------------------------------------------------------------
diff --git a/event/pom.xml b/event/pom.xml
index 748e5e6..9b9b393 100644
--- a/event/pom.xml
+++ b/event/pom.xml
@@ -44,7 +44,7 @@
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
-                        <_dsannotations>*</_dsannotations>
+                        <Bundle-Activator>org.apache.karaf.event.service.Activator</Bundle-Activator>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/EventDisplayCommand.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/EventDisplayCommand.java b/event/src/main/java/org/apache/karaf/event/EventDisplayCommand.java
deleted file mode 100644
index 37d8f3c..0000000
--- a/event/src/main/java/org/apache/karaf/event/EventDisplayCommand.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import static org.apache.karaf.event.service.TopicPredicate.matchTopic;
-
-import org.apache.karaf.event.service.EventCollector;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.osgi.framework.BundleContext;
-
-@Command(scope = "event", name = "display", description = "Shows events")
-@Service
-public class EventDisplayCommand implements Action {
-
-    @Reference
-    Session session;
-
-    @Reference
-    BundleContext context;
-
-    @Reference
-    EventCollector collector;
-
-    @Argument
-    String topicFilter = "*";
-
-    @Option(name = "-v")
-    boolean verbose = false;
-
-    @Override
-    public Object execute() throws Exception {
-        EventPrinter printer = new EventPrinter(session.getConsole(), verbose);
-        collector.getEvents().filter(matchTopic(topicFilter)).forEach(printer);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/EventPrinter.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/EventPrinter.java b/event/src/main/java/org/apache/karaf/event/EventPrinter.java
deleted file mode 100644
index 314dc9d..0000000
--- a/event/src/main/java/org/apache/karaf/event/EventPrinter.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import java.io.PrintStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.function.Consumer;
-
-import org.osgi.service.event.Event;
-
-public class EventPrinter implements Consumer<Event>{
-    private PrintStream out;
-    private boolean verbose;
-
-    public EventPrinter(PrintStream out, boolean verbose) {
-        this.out = out;
-        this.verbose = verbose;
-    }
-    
-
-    @Override
-    public void accept(Event event) {
-        out.println(getTimeStamp(event) + " - " + event.getTopic());
-        if (verbose) {
-            for (String key : event.getPropertyNames()) {
-                if (!key.equals("event.topics") && !key.equals("timestamp")) {
-                    out.println(key + ": " + getPrintValue(event, key));
-                }
-            }
-            out.println();
-            out.flush();
-        }
-    }
-
-    private String getTimeStamp(Event event) {
-        Long ts = (Long)event.getProperty("timestamp");
-        if (ts == null) {
-            return "0000-00-00 00:00:00";
-        }
-        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        return df.format(new Date(ts));
-    }
-
-    private Object getPrintValue(Event event, String key) {
-        Object value = event.getProperty(key);
-        if (value.getClass().isArray()) {
-            return Arrays.toString((Object[])value);
-        }
-        return value.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/EventSendCommand.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/EventSendCommand.java b/event/src/main/java/org/apache/karaf/event/EventSendCommand.java
deleted file mode 100644
index ba3ab1b..0000000
--- a/event/src/main/java/org/apache/karaf/event/EventSendCommand.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-
-@Command(scope = "event", name = "send", description = "Send a simple event to a topic")
-@Service
-public class EventSendCommand implements Action {
-    @Reference
-    Session session;
-    
-    @Reference
-    EventAdmin eventAdmin;
-
-    @Argument
-    String topic;
-
-    @Argument(multiValued=true)
-    String propertiesSt;
-
-    @Override
-    public Object execute() throws Exception {
-        eventAdmin.sendEvent(new Event(topic, parse(propertiesSt)));
-        return null;
-    }
-
-    Map<String, String> parse(String propSt) {
-        Map<String, String> properties = new HashMap<>();
-        for (String keyValue : propSt.split(",")) {
-            String[] splitted = keyValue.split("=");
-            if (splitted.length != 2) {
-                throw new IllegalArgumentException("Invalid entry " + keyValue);
-            }
-            properties.put(splitted[0], splitted[1]);
-        };
-        return properties;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/EventTailCommand.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/EventTailCommand.java b/event/src/main/java/org/apache/karaf/event/EventTailCommand.java
deleted file mode 100644
index 7be8840..0000000
--- a/event/src/main/java/org/apache/karaf/event/EventTailCommand.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import static org.apache.karaf.event.service.TopicPredicate.matchTopic;
-
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-
-import org.apache.karaf.event.service.EventCollector;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.event.Event;
-
-@Command(scope = "event", name = "tail", description = "Shows events and listens for incoming events")
-@Service
-public class EventTailCommand implements Action {
-
-    @Reference
-    Session session;
-
-    @Reference
-    BundleContext context;
-
-    @Reference
-    EventCollector collector;
-
-    @Argument
-    String topicFilter = "*";
-
-    @Option(name = "-v")
-    boolean verbose = false;
-
-    @Override
-    public Object execute() throws Exception {
-        EventPrinter printer = new EventPrinter(session.getConsole(), verbose);
-        Consumer<Event> filteredPrinter = executeIf(matchTopic(topicFilter), printer);
-        collector.addConsumer(filteredPrinter);
-        try {
-            waitTillInterrupted();
-        } catch (InterruptedException e) {
-            collector.removeConsumer(filteredPrinter);
-        }
-        return null;
-    }
-    
-    private <T> Consumer<T> executeIf(Predicate<T> pred, Consumer<T> consumer) {
-        return t -> {if (pred.test(t)) consumer.accept(t);};
-    }
-
-    private void waitTillInterrupted() throws InterruptedException {
-        while (true) {
-            Thread.sleep(100);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/command/EventDisplayCommand.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/command/EventDisplayCommand.java b/event/src/main/java/org/apache/karaf/event/command/EventDisplayCommand.java
new file mode 100644
index 0000000..f53b5bf
--- /dev/null
+++ b/event/src/main/java/org/apache/karaf/event/command/EventDisplayCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import static org.apache.karaf.event.service.TopicPredicate.matchTopic;
+
+import org.apache.karaf.event.service.EventCollector;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.osgi.framework.BundleContext;
+
+@Command(scope = "event", name = "display", description = "Shows events")
+@Service
+public class EventDisplayCommand implements Action {
+
+    @Reference
+    Session session;
+
+    @Reference
+    BundleContext context;
+
+    @Reference
+    EventCollector collector;
+
+    @Argument
+    String topicFilter = "*";
+
+    @Option(name = "-v")
+    boolean verbose = false;
+
+    @Override
+    public Object execute() throws Exception {
+        EventPrinter printer = new EventPrinter(session.getConsole(), verbose);
+        collector.getEvents().filter(matchTopic(topicFilter)).forEach(printer);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/command/EventPrinter.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/command/EventPrinter.java b/event/src/main/java/org/apache/karaf/event/command/EventPrinter.java
new file mode 100644
index 0000000..9736e40
--- /dev/null
+++ b/event/src/main/java/org/apache/karaf/event/command/EventPrinter.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import java.io.PrintStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.function.Consumer;
+
+import org.osgi.service.event.Event;
+
+public class EventPrinter implements Consumer<Event>{
+    private PrintStream out;
+    private boolean verbose;
+
+    public EventPrinter(PrintStream out, boolean verbose) {
+        this.out = out;
+        this.verbose = verbose;
+    }
+    
+
+    @Override
+    public void accept(Event event) {
+        out.println(getTimeStamp(event) + " - " + event.getTopic());
+        if (verbose) {
+            for (String key : event.getPropertyNames()) {
+                if (!key.equals("event.topics") && !key.equals("timestamp")) {
+                    out.println(key + ": " + getPrintValue(event, key));
+                }
+            }
+            out.println();
+            out.flush();
+        }
+    }
+
+    private String getTimeStamp(Event event) {
+        Long ts = (Long)event.getProperty("timestamp");
+        if (ts == null) {
+            return "0000-00-00 00:00:00";
+        }
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return df.format(new Date(ts));
+    }
+
+    private Object getPrintValue(Event event, String key) {
+        Object value = event.getProperty(key);
+        if (value.getClass().isArray()) {
+            return Arrays.toString((Object[])value);
+        }
+        return value.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/command/EventSendCommand.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/command/EventSendCommand.java b/event/src/main/java/org/apache/karaf/event/command/EventSendCommand.java
new file mode 100644
index 0000000..092facb
--- /dev/null
+++ b/event/src/main/java/org/apache/karaf/event/command/EventSendCommand.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+@Command(scope = "event", name = "send", description = "Send a simple event to a topic")
+@Service
+public class EventSendCommand implements Action {
+    @Reference
+    Session session;
+    
+    @Reference
+    EventAdmin eventAdmin;
+
+    @Argument
+    String topic;
+
+    @Argument(multiValued=true)
+    String propertiesSt;
+
+    @Override
+    public Object execute() throws Exception {
+        eventAdmin.sendEvent(new Event(topic, parse(propertiesSt)));
+        return null;
+    }
+
+    Map<String, String> parse(String propSt) {
+        Map<String, String> properties = new HashMap<>();
+        for (String keyValue : propSt.split(",")) {
+            String[] splitted = keyValue.split("=");
+            if (splitted.length != 2) {
+                throw new IllegalArgumentException("Invalid entry " + keyValue);
+            }
+            properties.put(splitted[0], splitted[1]);
+        };
+        return properties;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/command/EventTailCommand.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/command/EventTailCommand.java b/event/src/main/java/org/apache/karaf/event/command/EventTailCommand.java
new file mode 100644
index 0000000..b6592fc
--- /dev/null
+++ b/event/src/main/java/org/apache/karaf/event/command/EventTailCommand.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import static org.apache.karaf.event.service.TopicPredicate.matchTopic;
+
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+import org.apache.karaf.event.service.EventCollector;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.event.Event;
+
+@Command(scope = "event", name = "tail", description = "Shows events and listens for incoming events")
+@Service
+public class EventTailCommand implements Action {
+
+    @Reference
+    Session session;
+
+    @Reference
+    BundleContext context;
+
+    @Reference
+    EventCollector collector;
+
+    @Argument
+    String topicFilter = "*";
+
+    @Option(name = "-v")
+    boolean verbose = false;
+
+    @Override
+    public Object execute() throws Exception {
+        EventPrinter printer = new EventPrinter(session.getConsole(), verbose);
+        Consumer<Event> filteredPrinter = executeIf(matchTopic(topicFilter), printer);
+        collector.addConsumer(filteredPrinter);
+        try {
+            waitTillInterrupted();
+        } catch (InterruptedException e) {
+            collector.removeConsumer(filteredPrinter);
+        }
+        return null;
+    }
+    
+    private <T> Consumer<T> executeIf(Predicate<T> pred, Consumer<T> consumer) {
+        return t -> {if (pred.test(t)) consumer.accept(t);};
+    }
+
+    private void waitTillInterrupted() throws InterruptedException {
+        while (true) {
+            Thread.sleep(100);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/main/java/org/apache/karaf/event/service/Activator.java
----------------------------------------------------------------------
diff --git a/event/src/main/java/org/apache/karaf/event/service/Activator.java b/event/src/main/java/org/apache/karaf/event/service/Activator.java
new file mode 100644
index 0000000..11f3897
--- /dev/null
+++ b/event/src/main/java/org/apache/karaf/event/service/Activator.java
@@ -0,0 +1,25 @@
+package org.apache.karaf.event.service;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.event.EventHandler;
+
+public class Activator implements BundleActivator {
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        EventCollector collector = new EventCollector();
+        Dictionary<String, String> props = new Hashtable<>();
+        props.put("event.topics", "*");
+        String[] ifAr = new String[]{EventHandler.class.getName(), EventCollector.class.getName()};
+        context.registerService(ifAr, collector, props);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/EventDisplayCommandTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/EventDisplayCommandTest.java b/event/src/test/java/org/apache/karaf/event/EventDisplayCommandTest.java
deleted file mode 100644
index 0822f73..0000000
--- a/event/src/test/java/org/apache/karaf/event/EventDisplayCommandTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import static org.easymock.EasyMock.createControl;
-import static org.easymock.EasyMock.expect;
-
-import java.util.HashMap;
-
-import org.apache.karaf.event.service.EventCollector;
-import org.apache.karaf.shell.api.console.Session;
-import org.easymock.IMocksControl;
-import org.junit.Test;
-import org.osgi.service.event.Event;
-
-public class EventDisplayCommandTest {
-
-    @Test
-    public void testExecute() throws Exception {
-        IMocksControl c = createControl();
-        EventDisplayCommand display = new EventDisplayCommand();
-        display.session = c.createMock(Session.class);
-        expect(display.session.getConsole()).andReturn(System.out);
-        display.collector = new EventCollector();
-        display.collector.handleEvent(new Event("myTopic", new HashMap<>()));
-        c.replay();
-        display.execute();
-        c.verify();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/EventPrinterTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/EventPrinterTest.java b/event/src/test/java/org/apache/karaf/event/EventPrinterTest.java
deleted file mode 100644
index cee5b0f..0000000
--- a/event/src/test/java/org/apache/karaf/event/EventPrinterTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-
-import org.junit.Test;
-import org.osgi.service.event.Event;
-
-public class EventPrinterTest {
-    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
-
-    @Test
-    public void testPrint() throws UnsupportedEncodingException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream out = new PrintStream(baos);
-        new EventPrinter(out, false).accept(event());
-        String result = baos.toString("utf-8");
-        assertThat(result, equalTo("2016-01-01 12:00:00 - myTopic\n"));
-    }
-    
-    @Test
-    public void testPrintVerbose() throws UnsupportedEncodingException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream out = new PrintStream(baos);
-        new EventPrinter(out, true).accept(event());
-        String result = baos.toString("utf-8");
-        assertThat(result, equalTo("2016-01-01 12:00:00 - myTopic\n" 
-            + "a: b\n"
-            + "c: [d, e]\n\n"));
-    }
-
-    private Event event() {
-        HashMap<String, Object> props = new HashMap<>();
-        props.put("a", "b");
-        props.put("c", new String[]{"d", "e"});
-        Date date;
-        try {
-            date = df.parse("2016-01-01 12:00:00");
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
-        props.put("timestamp",  date.getTime());
-        return new Event("myTopic", props);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/EventSendCommandTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/EventSendCommandTest.java b/event/src/test/java/org/apache/karaf/event/EventSendCommandTest.java
deleted file mode 100644
index fb87c4b..0000000
--- a/event/src/test/java/org/apache/karaf/event/EventSendCommandTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.apache.karaf.event;
-
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.mock;
-import static org.easymock.EasyMock.newCapture;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.easymock.Capture;
-import org.junit.Test;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-
-public class EventSendCommandTest {
-    @Test
-    public void testExecute() throws Exception {
-        EventSendCommand send = new EventSendCommand();
-        send.eventAdmin = mock(EventAdmin.class);
-        Capture<Event> eventCapture = newCapture();
-        send.eventAdmin.sendEvent(capture(eventCapture));
-        expectLastCall();
-
-        replay(send.eventAdmin);
-        send.topic = "myTopic";
-        send.propertiesSt = "a=b";
-        send.execute();
-        verify(send.eventAdmin);
-        
-        Event event = eventCapture.getValue();
-        assertThat(event.getTopic(), equalTo("myTopic"));
-        assertThat(event.getProperty("a"), equalTo("b"));
-    }
-    
-    @Test
-    public void testParse() {
-        String propSt = "a=b,b=c";
-        Map<String, String> expectedMap = new HashMap<>();
-        expectedMap.put("a", "b");
-        expectedMap.put("b", "c");
-        Map<String, String> props = new EventSendCommand().parse(propSt);
-        assertThat(props.entrySet(), equalTo(expectedMap.entrySet())); 
-    }
-    
-    @Test(expected=IllegalArgumentException.class)
-    public void testParseError() {
-        String propSt = "a=b,c=";
-        new EventSendCommand().parse(propSt);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/EventTailCommandTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/EventTailCommandTest.java b/event/src/test/java/org/apache/karaf/event/EventTailCommandTest.java
deleted file mode 100644
index b18f725..0000000
--- a/event/src/test/java/org/apache/karaf/event/EventTailCommandTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.event;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.mock;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.karaf.event.service.EventCollector;
-import org.apache.karaf.shell.api.console.Session;
-import org.junit.Test;
-import org.osgi.service.event.Event;
-
-public class EventTailCommandTest {
-
-    private Exception exception;
-
-    @Test
-    public void testTail() throws Exception {
-        EventTailCommand tail = new EventTailCommand();
-        tail.session = mock(Session.class);
-        tail.collector = new EventCollector();
-        PrintStream out = System.out;
-        expect(tail.session.getConsole()).andReturn(out);
-        exception = null;
-        replay(tail.session);
-        
-        ExecutorService executor = Executors.newSingleThreadExecutor();
-        executor.execute(() -> {
-            try {
-                tail.execute();
-            } catch (Exception e) {
-                exception = e;
-            }
-        });
-        tail.collector.handleEvent(event());
-        Thread.sleep(200);
-        executor.shutdownNow();
-        executor.awaitTermination(100, TimeUnit.SECONDS);
-        if (exception != null) {
-            throw exception;
-        }
-        verify(tail.session);
-    }
-
-    private Event event() {
-        return new Event("myTopic", new HashMap<>());
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/command/EventDisplayCommandTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/command/EventDisplayCommandTest.java b/event/src/test/java/org/apache/karaf/event/command/EventDisplayCommandTest.java
new file mode 100644
index 0000000..ee159ff
--- /dev/null
+++ b/event/src/test/java/org/apache/karaf/event/command/EventDisplayCommandTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.expect;
+
+import java.util.HashMap;
+
+import org.apache.karaf.event.command.EventDisplayCommand;
+import org.apache.karaf.event.service.EventCollector;
+import org.apache.karaf.shell.api.console.Session;
+import org.easymock.IMocksControl;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+
+public class EventDisplayCommandTest {
+
+    @Test
+    public void testExecute() throws Exception {
+        IMocksControl c = createControl();
+        EventDisplayCommand display = new EventDisplayCommand();
+        display.session = c.createMock(Session.class);
+        expect(display.session.getConsole()).andReturn(System.out);
+        display.collector = new EventCollector();
+        display.collector.handleEvent(new Event("myTopic", new HashMap<>()));
+        c.replay();
+        display.execute();
+        c.verify();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/command/EventPrinterTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/command/EventPrinterTest.java b/event/src/test/java/org/apache/karaf/event/command/EventPrinterTest.java
new file mode 100644
index 0000000..d0dea2a
--- /dev/null
+++ b/event/src/test/java/org/apache/karaf/event/command/EventPrinterTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+
+import org.apache.karaf.event.command.EventPrinter;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+
+public class EventPrinterTest {
+    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+
+    @Test
+    public void testPrint() throws UnsupportedEncodingException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream out = new PrintStream(baos);
+        new EventPrinter(out, false).accept(event());
+        String result = baos.toString("utf-8");
+        assertThat(result, equalTo("2016-01-01 12:00:00 - myTopic\n"));
+    }
+    
+    @Test
+    public void testPrintVerbose() throws UnsupportedEncodingException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream out = new PrintStream(baos);
+        new EventPrinter(out, true).accept(event());
+        String result = baos.toString("utf-8");
+        assertThat(result, equalTo("2016-01-01 12:00:00 - myTopic\n" 
+            + "a: b\n"
+            + "c: [d, e]\n\n"));
+    }
+
+    private Event event() {
+        HashMap<String, Object> props = new HashMap<>();
+        props.put("a", "b");
+        props.put("c", new String[]{"d", "e"});
+        Date date;
+        try {
+            date = df.parse("2016-01-01 12:00:00");
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+        props.put("timestamp",  date.getTime());
+        return new Event("myTopic", props);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/command/EventSendCommandTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/command/EventSendCommandTest.java b/event/src/test/java/org/apache/karaf/event/command/EventSendCommandTest.java
new file mode 100644
index 0000000..ba56179
--- /dev/null
+++ b/event/src/test/java/org/apache/karaf/event/command/EventSendCommandTest.java
@@ -0,0 +1,56 @@
+package org.apache.karaf.event.command;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.mock;
+import static org.easymock.EasyMock.newCapture;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.karaf.event.command.EventSendCommand;
+import org.easymock.Capture;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+public class EventSendCommandTest {
+    @Test
+    public void testExecute() throws Exception {
+        EventSendCommand send = new EventSendCommand();
+        send.eventAdmin = mock(EventAdmin.class);
+        Capture<Event> eventCapture = newCapture();
+        send.eventAdmin.sendEvent(capture(eventCapture));
+        expectLastCall();
+
+        replay(send.eventAdmin);
+        send.topic = "myTopic";
+        send.propertiesSt = "a=b";
+        send.execute();
+        verify(send.eventAdmin);
+        
+        Event event = eventCapture.getValue();
+        assertThat(event.getTopic(), equalTo("myTopic"));
+        assertThat(event.getProperty("a"), equalTo("b"));
+    }
+    
+    @Test
+    public void testParse() {
+        String propSt = "a=b,b=c";
+        Map<String, String> expectedMap = new HashMap<>();
+        expectedMap.put("a", "b");
+        expectedMap.put("b", "c");
+        Map<String, String> props = new EventSendCommand().parse(propSt);
+        assertThat(props.entrySet(), equalTo(expectedMap.entrySet())); 
+    }
+    
+    @Test(expected=IllegalArgumentException.class)
+    public void testParseError() {
+        String propSt = "a=b,c=";
+        new EventSendCommand().parse(propSt);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d315b32e/event/src/test/java/org/apache/karaf/event/command/EventTailCommandTest.java
----------------------------------------------------------------------
diff --git a/event/src/test/java/org/apache/karaf/event/command/EventTailCommandTest.java b/event/src/test/java/org/apache/karaf/event/command/EventTailCommandTest.java
new file mode 100644
index 0000000..01287c7
--- /dev/null
+++ b/event/src/test/java/org/apache/karaf/event/command/EventTailCommandTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.event.command;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.mock;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.karaf.event.command.EventTailCommand;
+import org.apache.karaf.event.service.EventCollector;
+import org.apache.karaf.shell.api.console.Session;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+
+public class EventTailCommandTest {
+
+    private Exception exception;
+
+    @Test
+    public void testTail() throws Exception {
+        EventTailCommand tail = new EventTailCommand();
+        tail.session = mock(Session.class);
+        tail.collector = new EventCollector();
+        PrintStream out = System.out;
+        expect(tail.session.getConsole()).andReturn(out);
+        exception = null;
+        replay(tail.session);
+        
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        executor.execute(() -> {
+            try {
+                tail.execute();
+            } catch (Exception e) {
+                exception = e;
+            }
+        });
+        tail.collector.handleEvent(event());
+        Thread.sleep(200);
+        executor.shutdownNow(); // Will interrupt the tail
+        executor.awaitTermination(10, TimeUnit.SECONDS);
+        if (exception != null) {
+            throw exception;
+        }
+        verify(tail.session);
+    }
+
+    private Event event() {
+        return new Event("myTopic", new HashMap<>());
+    }
+}