diff --git a/akka-bbb-apps/build.sbt b/akka-bbb-apps/build.sbt
index af6c93edc018133d6157c388642194f9447837e8..1a4da064d35b82d6e584ef2784cba7290eb5db75 100755
--- a/akka-bbb-apps/build.sbt
+++ b/akka-bbb-apps/build.sbt
@@ -1,33 +1,34 @@
-enablePlugins(JavaServerAppPackaging)
-
-name := "bbb-apps-akka"
-
-organization := "org.bigbluebutton"
+import org.bigbluebutton.build._
 
-version := "0.0.2"
+import scalariform.formatter.preferences._
+import com.typesafe.sbt.SbtScalariform
+import com.typesafe.sbt.SbtScalariform.ScalariformKeys
 
-scalaVersion := "2.12.6"
+import com.typesafe.sbt.SbtNativePackager.autoImport._
 
-scalacOptions ++= Seq(
-  "-unchecked",
-  "-deprecation",
-  "-Xlint",
-  "-Ywarn-dead-code",
-  "-language:_",
-  "-target:jvm-1.8",
-  "-encoding", "UTF-8"
-)
+enablePlugins(JavaServerAppPackaging)
 
-resolvers ++= Seq(
-  "spray repo" at "http://repo.spray.io/",
-  "rediscala" at "http://dl.bintray.com/etaty/maven",
-  "blindside-repos" at "http://blindside.googlecode.com/svn/repository/"
+version := "0.0.3"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
 )
 
-resolvers += Resolver.sonatypeRepo("releases")
-resolvers += Resolver.typesafeRepo("releases")
-
-publishTo := Some(Resolver.file("file",  new File(Path.userHome.absolutePath+"/dev/repo/maven-repo/releases" )) )
+publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath + "/dev/repo/maven-repo/releases")))
 
 // We want to have our jar files in lib_managed dir.
 // This way we'll have the right path when we import
@@ -38,75 +39,15 @@ testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console",
 
 testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
 
-val akkaVersion       = "2.5.14"
-val scalaTestVersion  = "3.0.5"
-
-libraryDependencies ++= {
-  Seq(
-    "ch.qos.logback"           %   "logback-classic"                      % "1.2.3"       % "runtime",
-    "junit"                    %   "junit"                                % "4.11",
-    "commons-codec"             %  "commons-codec"                        % "1.11",
-    "org.apache.commons"        %  "commons-lang3"                        % "3.7"
-  )
-}
-
-libraryDependencies += "org.bigbluebutton" % "bbb-common-message_2.12" % "0.0.19-SNAPSHOT"
-
-// https://mvnrepository.com/artifact/org.scala-lang/scala-library
-libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value
-// https://mvnrepository.com/artifact/org.scala-lang/scala-compiler
-libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-actor_2.12" % akkaVersion
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-slf4j_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-slf4j_2.12" % akkaVersion
-
-// https://mvnrepository.com/artifact/com.github.etaty/rediscala_2.12
-libraryDependencies += "com.github.etaty" % "rediscala_2.12" % "1.8.0"
-
-libraryDependencies += "com.softwaremill.quicklens" %% "quicklens" % "1.4.11"
-libraryDependencies += "com.google.code.gson" % "gson" % "2.8.5"
-libraryDependencies += "joda-time" % "joda-time" % "2.10"
-libraryDependencies += "io.spray" % "spray-json_2.12" % "1.3.4"
-libraryDependencies += "org.parboiled" % "parboiled-scala_2.12" % "1.1.8"
-
-// https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-scala_2.12
-libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala_2.12" % "2.9.6"
+lazy val bbbAppsAkka = (project in file(".")).settings(name := "bbb-apps-akka", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
+scalariformAutoformat := false
 
-// For generating test reports
-libraryDependencies += "org.pegdown" % "pegdown" % "1.6.0" % "test"
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-testkit_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-testkit_2.12" % akkaVersion % "test"
-
-// https://mvnrepository.com/artifact/org.scalactic/scalactic_2.12
-libraryDependencies += "org.scalactic" % "scalactic_2.12" % "3.0.3" % "test"
-
-// https://mvnrepository.com/artifact/org.scalatest/scalatest_2.12
-libraryDependencies += "org.scalatest" % "scalatest_2.12" % scalaTestVersion % "test"
-
-libraryDependencies += "org.mockito" % "mockito-core" % "2.21.0" % "test"
-
-
-
-
-import com.typesafe.sbt.SbtScalariform
-
-import scalariform.formatter.preferences._
-import com.typesafe.sbt.SbtScalariform.ScalariformKeys
-
-SbtScalariform.defaultScalariformSettings
-
-ScalariformKeys.preferences := ScalariformKeys.preferences.value
+scalariformPreferences := scalariformPreferences.value
   .setPreference(AlignSingleLineCaseStatements, true)
-  .setPreference(DoubleIndentClassDeclaration, true)
+  .setPreference(DoubleIndentConstructorArguments, true)
   .setPreference(AlignParameters, true)
 
-
-
-
 //-----------
 // Packaging
 //
@@ -127,19 +68,12 @@ val user = "bigbluebutton"
 val group = "bigbluebutton"
 
 // user which will execute the application
-daemonUser in Linux := user        
+daemonUser in Linux := user
 
 // group which will execute the application
-daemonGroup in Linux := group 
-
-mappings in Universal <+= (packageBin in Compile, sourceDirectory ) map { (_, src) =>
-    // Move the application.conf so the user can override settings here
-    val appConf = src / "main" / "resources" / "application.conf"
-    appConf -> "conf/application.conf"
-}
-
-mappings in Universal <+= (packageBin in Compile, sourceDirectory ) map { (_, src) =>
-    // Move logback.xml so the user can override settings here    
-    val logConf = src / "main" / "resources" / "logback.xml"
-    logConf -> "conf/logback.xml"
-}
+daemonGroup in Linux := group
+
+mappings in(Universal, packageBin) += file("src/main/resources/application.conf") -> "conf/application.conf"
+mappings in(Universal, packageBin) += file("src/main/resources/logback.xml") -> "conf/logback.xml"
+
+debianPackageDependencies in Debian ++= Seq("java8-runtime-headless", "bash")
diff --git a/akka-bbb-apps/project/Build.scala b/akka-bbb-apps/project/Build.scala
deleted file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/akka-bbb-apps/project/Dependencies.scala b/akka-bbb-apps/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..005bd86a3736ad7367cc7d73366786e266a29072
--- /dev/null
+++ b/akka-bbb-apps/project/Dependencies.scala
@@ -0,0 +1,83 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+    val junit = "4.12"
+    val junitInterface = "0.11"
+    val scalactic = "3.0.3"
+
+    // Libraries
+    val akkaVersion = "2.5.17"
+    val gson = "2.8.5"
+    val jackson = "2.9.7"
+    val logback = "1.2.3"
+    val quicklens = "1.4.11"
+    val spray = "1.3.4"
+
+    // Apache Commons
+    val lang = "3.8.1"
+    val codec = "1.11"
+
+    // BigBlueButton
+    val bbbCommons = "0.0.20-SNAPSHOT"
+
+    // Test
+    val scalaTest = "3.0.5"
+    val mockito = "2.23.0"
+    val akkaTestKit = "2.5.18"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaCompiler = "org.scala-lang" % "scala-compiler" % Versions.scala
+
+    val akkaActor = "com.typesafe.akka" % "akka-actor_2.12" % Versions.akkaVersion
+    val akkaSl4fj = "com.typesafe.akka" % "akka-slf4j_2.12" % Versions.akkaVersion
+
+    val googleGson = "com.google.code.gson" % "gson" % Versions.gson
+    val jacksonModule = "com.fasterxml.jackson.module" %% "jackson-module-scala" % Versions.jackson
+    val quicklens = "com.softwaremill.quicklens" %% "quicklens" % Versions.quicklens
+    val logback = "ch.qos.logback" % "logback-classic" % Versions.logback % "runtime"
+    val commonsCodec = "commons-codec" % "commons-codec" % Versions.codec
+    val sprayJson = "io.spray" % "spray-json_2.12" % Versions.spray
+
+    val apacheLang = "org.apache.commons" % "commons-lang3" % Versions.lang
+
+    val bbbCommons = "org.bigbluebutton" % "bbb-common-message_2.12" % Versions.bbbCommons
+  }
+
+  object Test {
+    val scalaTest = "org.scalatest" %% "scalatest" % Versions.scalaTest % "test"
+    val junit = "junit" % "junit" % Versions.junit % "test"
+    val mockitoCore = "org.mockito" % "mockito-core" % Versions.mockito % "test"
+    val scalactic = "org.scalactic" % "scalactic_2.12" % Versions.scalactic % "test"
+    val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % Versions.akkaTestKit % "test"
+  }
+
+  val testing = Seq(
+    Test.scalaTest,
+    Test.junit,
+    Test.mockitoCore,
+    Test.scalactic,
+    Test.akkaTestKit)
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaCompiler,
+    Compile.akkaActor,
+    Compile.akkaSl4fj,
+    Compile.googleGson,
+    Compile.jacksonModule,
+    Compile.quicklens,
+    Compile.logback,
+    Compile.commonsCodec,
+    Compile.sprayJson,
+    Compile.apacheLang,
+    Compile.bbbCommons) ++ testing
+}
\ No newline at end of file
diff --git a/akka-bbb-apps/project/build.properties b/akka-bbb-apps/project/build.properties
index a6e117b61042ee81c62ba3a0fc5210d9502944df..2e6e3d24608ee15e892ed3b16d84224f7667e808 100755
--- a/akka-bbb-apps/project/build.properties
+++ b/akka-bbb-apps/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=1.2.6
\ No newline at end of file
diff --git a/akka-bbb-apps/project/plugins.sbt b/akka-bbb-apps/project/plugins.sbt
index ec155bbffce66550d65b058d63ef45fea0fa8b56..bc8c448553a2010f0c76ea69ccb7917f51ffef8a 100755
--- a/akka-bbb-apps/project/plugins.sbt
+++ b/akka-bbb-apps/project/plugins.sbt
@@ -1,11 +1,11 @@
 addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
-addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
+addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.2.0")
+addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
 
-addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")
+addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.12")
 
-addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
+addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.8")
 
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
diff --git a/akka-bbb-apps/run.sh b/akka-bbb-apps/run.sh
index 4015c4f1373a8caa1271bb9fa175c5940624bf89..fb253febdd48027f6337030036ed2384a76c1714 100755
--- a/akka-bbb-apps/run.sh
+++ b/akka-bbb-apps/run.sh
@@ -1,3 +1 @@
-sbt clean
-sbt run
-
+sbt clean run
diff --git a/akka-bbb-apps/src/main/resources/application.conf b/akka-bbb-apps/src/main/resources/application.conf
index e6904f7e9d99b9aae44fb0428072f15ebef56a5c..591f22a88f5ef2613020407b8dc6f493bb6cf046 100755
--- a/akka-bbb-apps/src/main/resources/application.conf
+++ b/akka-bbb-apps/src/main/resources/application.conf
@@ -10,7 +10,7 @@ akka {
   loggers = ["akka.event.slf4j.Slf4jLogger"]
   loglevel = "DEBUG"
   
-  rediscala-publish-worker-dispatcher {
+  redis-publish-worker-dispatcher {
       mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
       # Throughput defines the maximum number of messages to be
       # processed per actor before the thread jumps to the next actor.
@@ -18,7 +18,7 @@ akka {
       throughput = 512
     }
     
-  rediscala-subscriber-worker-dispatcher {
+  redis-subscriber-worker-dispatcher {
       mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
       # Throughput defines the maximum number of messages to be
       # processed per actor before the thread jumps to the next actor.
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala
index 74a852b9a5ce018e90f1a4db00c0762c53475526..82b54478421679653cf4b56766a8146660b531dc 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala
@@ -1,12 +1,18 @@
 package org.bigbluebutton
 
-import akka.event.Logging
-import akka.actor.ActorSystem
-import org.bigbluebutton.endpoint.redis.{ AppsRedisSubscriberActor, KeepAliveRedisPublisher, RedisPublisher, RedisRecorderActor }
+import org.bigbluebutton.common2.redis.RedisPublisher
 import org.bigbluebutton.core._
 import org.bigbluebutton.core.bus._
 import org.bigbluebutton.core.pubsub.senders.ReceivedJsonMsgHandlerActor
-import org.bigbluebutton.core2.{ AnalyticsActor, FromAkkaAppsMsgSenderActor }
+import org.bigbluebutton.core2.AnalyticsActor
+import org.bigbluebutton.core2.FromAkkaAppsMsgSenderActor
+import org.bigbluebutton.endpoint.redis.AppsRedisSubscriberActor
+import org.bigbluebutton.endpoint.redis.RedisRecorderActor
+
+import akka.actor.ActorSystem
+import akka.event.Logging
+import org.bigbluebutton.common2.redis.MessageSender
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
 
 object Boot extends App with SystemConfiguration {
 
@@ -22,7 +28,7 @@ object Boot extends App with SystemConfiguration {
 
   val outGW = new OutMessageGatewayImp(outBus2)
 
-  val redisPublisher = new RedisPublisher(system)
+  val redisPublisher = new RedisPublisher(system, "BbbAppsAkkaPub")
   val msgSender = new MessageSender(redisPublisher)
 
   val redisRecorderActor = system.actorOf(RedisRecorderActor.props(system), "redisRecorderActor")
@@ -46,8 +52,5 @@ object Boot extends App with SystemConfiguration {
   val redisMessageHandlerActor = system.actorOf(ReceivedJsonMsgHandlerActor.props(bbbMsgBus, incomingJsonMessageBus))
   incomingJsonMessageBus.subscribe(redisMessageHandlerActor, toAkkaAppsJsonChannel)
 
-  val redisSubscriberActor = system.actorOf(AppsRedisSubscriberActor.props(incomingJsonMessageBus), "redis-subscriber")
-
-  val keepAliveRedisPublisher = new KeepAliveRedisPublisher(system, redisPublisher)
-
+  val redisSubscriberActor = system.actorOf(AppsRedisSubscriberActor.props(system, incomingJsonMessageBus), "redis-subscriber")
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
index d2986d262a88d84363f7870e563f11d981312a6f..743a4894c4acec763614b2f9d50ca560e59ba24b 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
@@ -1,15 +1,10 @@
 package org.bigbluebutton
 
-import com.typesafe.config.ConfigFactory
 import scala.util.Try
 
-trait SystemConfiguration {
+import org.bigbluebutton.common2.redis.RedisConfiguration
 
-  val config = ConfigFactory.load()
-
-  lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
-  lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
-  lazy val redisPassword = Try(config.getString("redis.password")).getOrElse("")
+trait SystemConfiguration extends RedisConfiguration {
 
   lazy val bbbWebHost = Try(config.getString("services.bbbWebHost")).getOrElse("localhost")
   lazy val bbbWebPort = Try(config.getInt("services.bbbWebPort")).getOrElse(8888)
@@ -31,8 +26,6 @@ trait SystemConfiguration {
   lazy val outBbbMsgMsgChannel = Try(config.getString("eventBus.outBbbMsgMsgChannel")).getOrElse("OutBbbMsgChannel")
   lazy val recordServiceMessageChannel = Try(config.getString("eventBus.recordServiceMessageChannel")).getOrElse("RecordServiceMessageChannel")
 
-  lazy val toAkkaAppsRedisChannel = Try(config.getString("redis.toAkkaAppsRedisChannel")).getOrElse("to-akka-apps-redis-channel")
-  lazy val fromAkkaAppsRedisChannel = Try(config.getString("redis.fromAkkaAppsRedisChannel")).getOrElse("from-akka-apps-redis-channel")
   lazy val toHTML5RedisChannel = Try(config.getString("redis.toHTML5RedisChannel")).getOrElse("to-html5-redis-channel")
   lazy val fromAkkaAppsChannel = Try(config.getString("eventBus.fromAkkaAppsChannel")).getOrElse("from-akka-apps-channel")
   lazy val toAkkaAppsChannel = Try(config.getString("eventBus.toAkkaAppsChannel")).getOrElse("to-akka-apps-channel")
@@ -41,21 +34,9 @@ trait SystemConfiguration {
   lazy val toAkkaAppsJsonChannel = Try(config.getString("eventBus.toAkkaAppsChannel")).getOrElse("to-akka-apps-json-channel")
   lazy val fromAkkaAppsJsonChannel = Try(config.getString("eventBus.fromAkkaAppsChannel")).getOrElse("from-akka-apps-json-channel")
 
-  lazy val toVoiceConfRedisChannel = Try(config.getString("redis.toVoiceConfRedisChannel")).getOrElse("to-voice-conf-redis-channel")
-  lazy val fromVoiceConfRedisChannel = Try(config.getString("redis.fromVoiceConfRedisChannel")).getOrElse("from-voice-conf-redis-channel")
-
-  lazy val fromAkkaAppsWbRedisChannel = Try(config.getString("redis.fromAkkaAppsWbRedisChannel")).getOrElse("from-akka-apps-wb-redis-channel")
-  lazy val fromAkkaAppsChatRedisChannel = Try(config.getString("redis.fromAkkaAppsChatRedisChannel")).getOrElse("from-akka-apps-chat-redis-channel")
-  lazy val fromAkkaAppsPresRedisChannel = Try(config.getString("redis.fromAkkaAppsPresRedisChannel")).getOrElse("from-akka-apps-pres-redis-channel")
-
   lazy val maxNumberOfNotes = Try(config.getInt("sharedNotes.maxNumberOfNotes")).getOrElse(3)
   lazy val maxNumberOfUndos = Try(config.getInt("sharedNotes.maxNumberOfUndos")).getOrElse(30)
 
-  lazy val httpInterface = Try(config.getString("http.interface")).getOrElse("")
-  lazy val httpPort = Try(config.getInt("http.port")).getOrElse(9090)
-  lazy val telizeHost = Try(config.getString("services.telizeHost")).getOrElse("")
-  lazy val telizePort = Try(config.getInt("services.telizePort")).getOrElse(80)
-
   lazy val applyPermissionCheck = Try(config.getBoolean("apps.checkPermissions")).getOrElse(false)
 
   lazy val voiceConfRecordPath = Try(config.getString("voiceConf.recordPath")).getOrElse("/var/freeswitch/meetings")
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSender.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSender.scala
deleted file mode 100755
index 250b1b3fba8c2b5f3a122f5cd54c168b7fdf30c4..0000000000000000000000000000000000000000
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSender.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bigbluebutton.core
-
-import org.bigbluebutton.endpoint.redis.RedisPublisher
-
-class MessageSender(publisher: RedisPublisher) {
-
-  def send(channel: String, data: String) {
-    publisher.publish(channel, data)
-  }
-}
\ No newline at end of file
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala
index b9ed6467939bf9dfa7d6b605361704b0524cdf01..1659cea34f42f3158217f41a95c6488a2661e88c 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala
@@ -22,7 +22,6 @@ trait RegisterUserReqMsgHdlr {
       BbbCommonEnvCoreMsg(envelope, event)
     }
 
-    val guestPolicy = liveMeeting.guestsWaiting.getGuestPolicy().policy
     val guestStatus = msg.body.guestStatus
 
     val regUser = RegisteredUsers.create(msg.body.intUserId, msg.body.extUserId,
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
index 7d762dbb11a7ba9e0a4d168621abb52967782224..639adf2ca10bf647b747d88e3ce40b85b2161391 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
@@ -6,7 +6,9 @@ import com.fasterxml.jackson.databind.JsonNode
 import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.core.bus._
 import org.bigbluebutton.core2.ReceivedMessageRouter
-import scala.reflect.runtime.universe._
+import scala.reflect.runtime.universe._
+import org.bigbluebutton.common2.bus.ReceivedJsonMessage
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
 
 object ReceivedJsonMsgHandlerActor {
   def props(eventBus: BbbMsgRouterEventBus, incomingJsonMessageBus: IncomingJsonMessageBus): Props =
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
index 3dfb958767ff633bdacc8d637a4f6d5bd743af33..cc18aec6b2d2f62dc28331fb8f88290ff4813588 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
@@ -21,7 +21,9 @@ package org.bigbluebutton.core.record.events
 
 import java.text.SimpleDateFormat
 
+import scala.collection.Map
 import scala.collection.mutable.HashMap
+
 import org.bigbluebutton.core.api.TimestampGenerator
 
 trait RecordEvent {
@@ -70,6 +72,7 @@ trait RecordEvent {
     eventMap.put(EVENT, event)
   }
 
+  // @fixme : not used anymore
   /**
    * Convert the event into a Map to be recorded.
    * @return
@@ -77,6 +80,7 @@ trait RecordEvent {
   final def toMap(): Map[String, String] = {
     eventMap.toMap
   }
+
 }
 
 object RecordEvent extends RecordEvent {
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala
index 2dcaaf0f1f44a96019243bbd968727a8ecc684ff..0061b110d6c0e6437a8ae2a1f9386594b08935ce 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala
@@ -3,8 +3,8 @@ package org.bigbluebutton.core2
 import akka.actor.{ Actor, ActorLogging, Props }
 import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.msgs._
-import org.bigbluebutton.common2.util.JsonUtil
-import org.bigbluebutton.core.MessageSender
+import org.bigbluebutton.common2.util.JsonUtil
+import org.bigbluebutton.common2.redis.MessageSender
 
 object FromAkkaAppsMsgSenderActor {
   def props(msgSender: MessageSender): Props = Props(classOf[FromAkkaAppsMsgSenderActor], msgSender)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/AkkaAppsRedisSubscriberActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/AkkaAppsRedisSubscriberActor.scala
new file mode 100755
index 0000000000000000000000000000000000000000..8e8ba2ebc6cdceb55bc6e8df8cb003267dd2bbb5
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/AkkaAppsRedisSubscriberActor.scala
@@ -0,0 +1,32 @@
+package org.bigbluebutton.endpoint.redis
+
+import org.bigbluebutton.SystemConfiguration
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
+import org.bigbluebutton.common2.redis.{ RedisSubscriber, RedisSubscriberProvider }
+
+import akka.actor.ActorSystem
+import akka.actor.Props
+
+object AppsRedisSubscriberActor extends RedisSubscriber {
+
+  val channels = Seq(toAkkaAppsRedisChannel, fromVoiceConfRedisChannel)
+  val patterns = Seq("bigbluebutton:to-bbb-apps:*", "bigbluebutton:from-voice-conf:*", "bigbluebutton:from-bbb-transcode:*")
+
+  def props(system: ActorSystem, jsonMsgBus: IncomingJsonMessageBus): Props =
+    Props(
+      classOf[AppsRedisSubscriberActor],
+      system, jsonMsgBus,
+      redisHost, redisPort,
+      channels, patterns).withDispatcher("akka.redis-subscriber-worker-dispatcher")
+}
+
+class AppsRedisSubscriberActor(
+  system:     ActorSystem,
+  jsonMsgBus: IncomingJsonMessageBus,
+  redisHost:  String, redisPort: Int,
+  channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
+  extends RedisSubscriberProvider(system, "BbbAppsAkkaSub", channels, patterns, jsonMsgBus) with SystemConfiguration {
+
+  addListener(toAkkaAppsJsonChannel)
+  subscribe()
+}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala
deleted file mode 100755
index 5a5a1424f59eaee4f6c91c2714e74bead3251766..0000000000000000000000000000000000000000
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bigbluebutton.endpoint.redis
-
-import akka.actor.Props
-import akka.actor.OneForOneStrategy
-import akka.actor.SupervisorStrategy.Resume
-import java.io.{ PrintWriter, StringWriter }
-import java.net.InetSocketAddress
-
-import redis.actors.RedisSubscriberActor
-import redis.api.pubsub.{ Message, PMessage }
-
-import scala.concurrent.duration._
-import org.bigbluebutton.SystemConfiguration
-import org.bigbluebutton.core.bus.{ IncomingJsonMessage, IncomingJsonMessageBus, ReceivedJsonMessage }
-import redis.api.servers.ClientSetname
-
-object AppsRedisSubscriberActor extends SystemConfiguration {
-
-  val TO_AKKA_APPS = "bbb:to-akka-apps"
-  val channels = Seq(toAkkaAppsRedisChannel, fromVoiceConfRedisChannel)
-  val patterns = Seq("bigbluebutton:to-bbb-apps:*", "bigbluebutton:from-voice-conf:*", "bigbluebutton:from-bbb-transcode:*")
-
-  def props(jsonMsgBus: IncomingJsonMessageBus): Props =
-    Props(classOf[AppsRedisSubscriberActor], jsonMsgBus,
-      redisHost, redisPort,
-      channels, patterns).withDispatcher("akka.rediscala-subscriber-worker-dispatcher")
-}
-
-class AppsRedisSubscriberActor(jsonMsgBus: IncomingJsonMessageBus, redisHost: String,
-                               redisPort: Int,
-                               channels:  Seq[String] = Nil, patterns: Seq[String] = Nil)
-    extends RedisSubscriberActor(
-      new InetSocketAddress(redisHost, redisPort),
-      channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") }) with SystemConfiguration {
-
-  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
-    case e: Exception => {
-      val sw: StringWriter = new StringWriter()
-      sw.write("An exception has been thrown on AppsRedisSubscriberActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
-      e.printStackTrace(new PrintWriter(sw))
-      log.error(sw.toString())
-      Resume
-    }
-  }
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  write(ClientSetname("BbbAppsAkkaSub").encodedRequest)
-
-  def onMessage(message: Message) {
-    if (message.channel == toAkkaAppsRedisChannel || message.channel == fromVoiceConfRedisChannel) {
-      val receivedJsonMessage = new ReceivedJsonMessage(message.channel, message.data.utf8String)
-      //log.debug(s"RECEIVED:\n [${receivedJsonMessage.channel}] \n ${receivedJsonMessage.data} \n")
-      jsonMsgBus.publish(IncomingJsonMessage(toAkkaAppsJsonChannel, receivedJsonMessage))
-    }
-  }
-
-  def onPMessage(pmessage: PMessage) {
-
-    // We don't use PSubscribe anymore, but an implementation of the method is required
-    //log.error("Should not be receiving a PMessage. It triggered on a match of pattern: " + pmessage.patternMatched)
-    //log.error(pmessage.data.utf8String)
-  }
-}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/KeepAliveRedisPublisher.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/KeepAliveRedisPublisher.scala
deleted file mode 100755
index 74aa6e4b7885620de866627bba075e45e28dba75..0000000000000000000000000000000000000000
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/KeepAliveRedisPublisher.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bigbluebutton.endpoint.redis
-
-import scala.concurrent.duration._
-import scala.concurrent.ExecutionContext.Implicits.global
-import akka.actor.ActorSystem
-import org.bigbluebutton.SystemConfiguration
-
-class KeepAliveRedisPublisher(val system: ActorSystem, sender: RedisPublisher) extends SystemConfiguration {
-
-  val startedOn = System.currentTimeMillis()
-
-  system.scheduler.schedule(2 seconds, 5 seconds) {
-    //val msg = new BbbAppsIsAliveMessage(startedOn, System.currentTimeMillis())
-    // sender.publish("bigbluebutton:from-bbb-apps:keepalive", msg.toJson())
-  }
-}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisPublisher.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisPublisher.scala
deleted file mode 100755
index 6af8a64ebb05093023cc7e90a0f445cce3170b8b..0000000000000000000000000000000000000000
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisPublisher.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bigbluebutton.endpoint.redis
-
-import redis.RedisClient
-import akka.actor.ActorSystem
-import org.bigbluebutton.SystemConfiguration
-import akka.util.ByteString
-
-class RedisPublisher(val system: ActorSystem) extends SystemConfiguration {
-
-  val redis = RedisClient(redisHost, redisPort)(system)
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  redis.clientSetname("BbbAppsAkkaPub")
-
-  def publish(channel: String, data: String) {
-    //println("PUBLISH TO [" + channel + "]: \n [" + data + "]")
-    redis.publish(channel, ByteString(data))
-  }
-
-}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala
index 7a01783d5b6448ad53fd98eb53a235f2829d284b..c3c68f726ad22021d7a1c68fc02aac5fb46cd217 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala
@@ -1,40 +1,30 @@
 package org.bigbluebutton.endpoint.redis
 
-import akka.actor.{ Actor, ActorLogging, ActorSystem, Props }
-import org.bigbluebutton.SystemConfiguration
-import redis.RedisClient
-import scala.concurrent.ExecutionContext.Implicits.global
 import scala.collection.immutable.StringOps
+import scala.collection.JavaConverters._
+
+import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.msgs._
-import org.bigbluebutton.core.record.events._
+import org.bigbluebutton.common2.redis.RedisStorageProvider
 import org.bigbluebutton.core.apps.groupchats.GroupChatApp
+import org.bigbluebutton.core.record.events._
+
+import akka.actor.Actor
+import akka.actor.ActorLogging
+import akka.actor.ActorSystem
+import akka.actor.Props
 
 object RedisRecorderActor {
   def props(system: ActorSystem): Props = Props(classOf[RedisRecorderActor], system)
 }
 
-class RedisRecorderActor(val system: ActorSystem)
-    extends SystemConfiguration
-    with Actor with ActorLogging {
-  val redis = RedisClient(redisHost, redisPort)(system)
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  redis.clientSetname("BbbAppsAkkaRecorder")
-
-  val COLON = ":"
-
-  private def record(session: String, message: collection.immutable.Map[String, String]): Unit = {
-    for {
-      msgid <- redis.incr("global:nextRecordedMsgId")
-      key = "recording" + COLON + session + COLON + msgid
-      _ <- redis.hmset(key.mkString, message)
-      _ <- redis.expire(key.mkString, keysExpiresInSec)
-      key2 = "meeting" + COLON + session + COLON + "recordings"
-      _ <- redis.rpush(key2.mkString, msgid.toString)
-      result <- redis.expire(key2.mkString, keysExpiresInSec)
-    } yield result
+class RedisRecorderActor(system: ActorSystem)
+  extends RedisStorageProvider(system, "BbbAppsAkkaRecorder")
+  with SystemConfiguration
+  with Actor with ActorLogging {
 
+  private def record(session: String, message: java.util.Map[java.lang.String, java.lang.String]): Unit = {
+    redis.recordAndExpire(session, message)
   }
 
   def receive = {
@@ -121,7 +111,7 @@ class RedisRecorderActor(val system: ActorSystem)
       ev.setMessage(msg.body.msg.message)
       ev.setColor(msg.body.msg.color)
 
-      record(msg.header.meetingId, ev.toMap)
+      record(msg.header.meetingId, ev.toMap.asJava)
     }
   }
 
@@ -129,7 +119,7 @@ class RedisRecorderActor(val system: ActorSystem)
     val ev = new ClearPublicChatRecordEvent()
     ev.setMeetingId(msg.header.meetingId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handlePresentationConversionCompletedEvtMsg(msg: PresentationConversionCompletedEvtMsg) {
@@ -139,7 +129,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPresentationName(msg.body.presentation.id)
     ev.setOriginalFilename(msg.body.presentation.name)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
 
     if (msg.body.presentation.current) {
       recordSharePresentationEvent(msg.header.meetingId, msg.body.podId, msg.body.presentation.id)
@@ -154,7 +144,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setSlide(getPageNum(msg.body.pageId))
     ev.setId(msg.body.pageId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleResizeAndMovePageEvtMsg(msg: ResizeAndMovePageEvtMsg) {
@@ -168,7 +158,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setWidthRatio(msg.body.widthRatio)
     ev.setHeightRatio(msg.body.heightRatio)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleRemovePresentationEvtMsg(msg: RemovePresentationEvtMsg) {
@@ -177,7 +167,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPodId(msg.body.podId)
     ev.setPresentationName(msg.body.presentationId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleSetPresentationDownloadableEvtMsg(msg: SetPresentationDownloadableEvtMsg) {
@@ -187,7 +177,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPresentationName(msg.body.presentationId)
     ev.setDownloadable(msg.body.downloadable)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleSetCurrentPresentationEvtMsg(msg: SetCurrentPresentationEvtMsg) {
@@ -200,7 +190,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPodId(msg.body.podId)
     ev.setCurrentPresenter(msg.body.currentPresenterId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleRemovePresentationPodEvtMsg(msg: RemovePresentationPodEvtMsg) {
@@ -208,7 +198,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setMeetingId(msg.header.meetingId)
     ev.setPodId(msg.body.podId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleSetPresenterInPodRespMsg(msg: SetPresenterInPodRespMsg) {
@@ -217,7 +207,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPodId(msg.body.podId)
     ev.setNextPresenterId(msg.body.nextPresenterId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def recordSharePresentationEvent(meetingId: String, podId: String, presentationId: String) {
@@ -227,7 +217,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPresentationName(presentationId)
     ev.setShare(true)
 
-    record(meetingId, ev.toMap)
+    record(meetingId, ev.toMap.asJava)
   }
 
   private def getPageNum(id: String): Integer = {
@@ -266,7 +256,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPosition(annotation.position)
     ev.addAnnotation(annotation.annotationInfo)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleSendCursorPositionEvtMsg(msg: SendCursorPositionEvtMsg) {
@@ -279,7 +269,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setXPercent(msg.body.xPercent)
     ev.setYPercent(msg.body.yPercent)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleClearWhiteboardEvtMsg(msg: ClearWhiteboardEvtMsg) {
@@ -291,7 +281,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setUserId(msg.body.userId)
     ev.setFullClear(msg.body.fullClear)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUndoWhiteboardEvtMsg(msg: UndoWhiteboardEvtMsg) {
@@ -302,7 +292,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setWhiteboardId(msg.body.whiteboardId)
     ev.setUserId(msg.body.userId)
     ev.setShapeId(msg.body.annotationId)
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUserJoinedMeetingEvtMsg(msg: UserJoinedMeetingEvtMsg): Unit = {
@@ -313,7 +303,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setName(msg.body.name)
     ev.setRole(msg.body.role)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUserLeftMeetingEvtMsg(msg: UserLeftMeetingEvtMsg): Unit = {
@@ -321,7 +311,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setMeetingId(msg.header.meetingId)
     ev.setUserId(msg.body.intId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handlePresenterAssignedEvtMsg(msg: PresenterAssignedEvtMsg): Unit = {
@@ -331,7 +321,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setName(msg.body.presenterName)
     ev.setAssignedBy(msg.body.assignedBy)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
   private def handleUserEmojiChangedEvtMsg(msg: UserEmojiChangedEvtMsg) {
     handleUserStatusChange(msg.header.meetingId, msg.body.userId, "emojiStatus", msg.body.emoji)
@@ -352,7 +342,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setStatus(statusName)
     ev.setValue(statusValue)
 
-    record(meetingId, ev.toMap)
+    record(meetingId, ev.toMap.asJava)
   }
 
   private def handleUserJoinedVoiceConfToClientEvtMsg(msg: UserJoinedVoiceConfToClientEvtMsg) {
@@ -365,7 +355,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setMuted(msg.body.muted)
     ev.setTalking(msg.body.talking)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUserLeftVoiceConfToClientEvtMsg(msg: UserLeftVoiceConfToClientEvtMsg) {
@@ -374,7 +364,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setBridge(msg.body.voiceConf)
     ev.setParticipant(msg.body.intId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUserMutedVoiceEvtMsg(msg: UserMutedVoiceEvtMsg) {
@@ -384,7 +374,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setParticipant(msg.body.intId)
     ev.setMuted(msg.body.muted)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUserTalkingVoiceEvtMsg(msg: UserTalkingVoiceEvtMsg) {
@@ -394,7 +384,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setParticipant(msg.body.intId)
     ev.setTalking(msg.body.talking)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleVoiceRecordingStartedEvtMsg(msg: VoiceRecordingStartedEvtMsg) {
@@ -404,7 +394,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setRecordingTimestamp(msg.body.timestamp)
     ev.setFilename(msg.body.stream)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleVoiceRecordingStoppedEvtMsg(msg: VoiceRecordingStoppedEvtMsg) {
@@ -414,7 +404,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setRecordingTimestamp(msg.body.timestamp)
     ev.setFilename(msg.body.stream)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleEditCaptionHistoryEvtMsg(msg: EditCaptionHistoryEvtMsg) {
@@ -426,7 +416,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setLocaleCode(msg.body.localeCode)
     ev.setText(msg.body.text)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleScreenshareRtmpBroadcastStartedEvtMsg(msg: ScreenshareRtmpBroadcastStartedEvtMsg) {
@@ -434,7 +424,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setMeetingId(msg.header.meetingId)
     ev.setStreamPath(msg.body.stream)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleScreenshareRtmpBroadcastStoppedEvtMsg(msg: ScreenshareRtmpBroadcastStoppedEvtMsg) {
@@ -442,7 +432,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setMeetingId(msg.header.meetingId)
     ev.setStreamPath(msg.body.stream)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   /*
@@ -462,7 +452,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setUserId(msg.body.setBy)
     ev.setRecordingStatus(msg.body.recording)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleRecordStatusResetSysMsg(msg: RecordStatusResetSysMsg) {
@@ -471,7 +461,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setUserId(msg.body.setBy)
     ev.setRecordingStatus(msg.body.recording)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleWebcamsOnlyForModeratorChangedEvtMsg(msg: WebcamsOnlyForModeratorChangedEvtMsg) {
@@ -480,14 +470,14 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setUserId(msg.body.setBy)
     ev.setWebcamsOnlyForModerator(msg.body.webcamsOnlyForModerator)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleEndAndKickAllSysMsg(msg: EndAndKickAllSysMsg): Unit = {
     val ev = new EndAndKickAllRecordEvent()
     ev.setMeetingId(msg.header.meetingId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleRecordingChapterBreakSysMsg(msg: RecordingChapterBreakSysMsg): Unit = {
@@ -495,7 +485,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setMeetingId(msg.header.meetingId)
     ev.setChapterBreakTimestamp(msg.body.timestamp)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handlePollStartedEvtMsg(msg: PollStartedEvtMsg): Unit = {
@@ -503,7 +493,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setPollId(msg.body.pollId)
     ev.setAnswers(msg.body.poll.answers)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handleUserRespondedToPollRecordMsg(msg: UserRespondedToPollRecordMsg): Unit = {
@@ -512,7 +502,7 @@ class RedisRecorderActor(val system: ActorSystem)
     ev.setUserId(msg.header.userId)
     ev.setAnswerId(msg.body.answerId)
 
-    record(msg.header.meetingId, ev.toMap)
+    record(msg.header.meetingId, ev.toMap.asJava)
   }
 
   private def handlePollStoppedEvtMsg(msg: PollStoppedEvtMsg): Unit = {
@@ -527,6 +517,6 @@ class RedisRecorderActor(val system: ActorSystem)
     val ev = new PollStoppedRecordEvent()
     ev.setPollId(pollId)
 
-    record(meetingId, ev.toMap)
+    record(meetingId, ev.toMap.asJava)
   }
 }
diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala
index fb2b3f5e7694a60e7140ea4158684e103b4a882b..3e57891347a7b653e8fe4392aea6854d7065ddc1 100755
--- a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala
+++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala
@@ -15,10 +15,16 @@ trait AppsTestFixtures {
   val meetingName = "test meeting"
   val record = false
   val voiceConfId = "85115"
+  val muteOnStart = true
   val deskshareConfId = "85115-DESKSHARE"
   val durationInMinutes = 10
   val maxInactivityTimeoutMinutes = 120
-  val warnMinutesBeforeMax = 5
+  val warnMinutesBeforeMax = 30
+  val meetingExpireIfNoUserJoinedInMinutes = 5
+  val meetingExpireWhenLastUserLeftInMinutes = 10
+  val userInactivityInspectTimerInMinutes = 60
+  val userInactivityThresholdInMinutes = 10
+  val userActivitySignResponseDelayInMinutes = 5
   val autoStartRecording = false
   val allowStartStopRecording = false
   val webcamsOnlyForModerator = false;
@@ -38,24 +44,19 @@ trait AppsTestFixtures {
   val red5DeskShareAppTestFixtures = "red5App"
   val metadata: collection.immutable.Map[String, String] = Map("foo" -> "bar", "bar" -> "baz", "baz" -> "foo")
   val screenshareProps = ScreenshareProps("TODO", "TODO", "TODO")
-  val breakoutProps = BreakoutProps(parentMeetingId, sequence, Vector())
+  val breakoutProps = BreakoutProps(parentId = parentMeetingId, sequence = sequence, freeJoin = false, breakoutRooms = Vector())
 
   val meetingProp = MeetingProp(name = meetingName, extId = externalMeetingId, intId = meetingId,
     isBreakout = isBreakout.booleanValue())
-  val durationProps = DurationProps(
-    duration = durationInMinutes,
-    createdTime = createTime, createdDate = createDate,
-    maxInactivityTimeoutMinutes = maxInactivityTimeoutMinutes,
-    warnMinutesBeforeMax = warnMinutesBeforeMax,
-    meetingExpireIfNoUserJoinedInMinutes = 5,
-    meetingExpireWhenLastUserLeftInMinutes = 1
-  )
+  val durationProps = DurationProps(duration = durationInMinutes, createdTime = createTime, createdDate = createDate, maxInactivityTimeoutMinutes = maxInactivityTimeoutMinutes, warnMinutesBeforeMax = warnMinutesBeforeMax,
+    meetingExpireIfNoUserJoinedInMinutes = meetingExpireIfNoUserJoinedInMinutes, meetingExpireWhenLastUserLeftInMinutes = meetingExpireWhenLastUserLeftInMinutes,
+    userInactivityInspectTimerInMinutes = userInactivityInspectTimerInMinutes, userInactivityThresholdInMinutes = userInactivityInspectTimerInMinutes, userActivitySignResponseDelayInMinutes = userActivitySignResponseDelayInMinutes)
   val password = PasswordProp(moderatorPass = moderatorPassword, viewerPass = viewerPassword)
   val recordProp = RecordProp(record = record, autoStartRecording = autoStartRecording,
     allowStartStopRecording = allowStartStopRecording)
   val welcomeProp = WelcomeProp(welcomeMsgTemplate = welcomeMsgTemplate, welcomeMsg = welcomeMsg,
     modOnlyMessage = modOnlyMessage)
-  val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber)
+  val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart)
   val usersProp = UsersProp(maxUsers = maxUsers, webcamsOnlyForModerator = webcamsOnlyForModerator,
     guestPolicy = guestPolicy)
   val metadataProp = new MetadataProp(metadata)
@@ -84,7 +85,6 @@ trait AppsTestFixtures {
     val layouts = new Layouts()
     val wbModel = new WhiteboardModel()
     val presModel = new PresentationModel()
-    val breakoutRooms = new BreakoutRooms()
     val captionModel = new CaptionModel()
     val notesModel = new SharedNotesModel()
     val registeredUsers = new RegisteredUsers
diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/domain/MeetingInactivityTrackerTests.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/domain/MeetingInactivityTrackerTests.scala
index 6a09dc346bd76bba763afeea65f961be87b4daed..95f8ab07d9f674a95c649813b873fe8e5c11c6da 100755
--- a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/domain/MeetingInactivityTrackerTests.scala
+++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/domain/MeetingInactivityTrackerTests.scala
@@ -1,7 +1,6 @@
 package org.bigbluebutton.core.domain
 
 import org.bigbluebutton.core.UnitSpec
-import org.bigbluebutton.core.running.MeetingExpiryTrackerHelper
 import org.bigbluebutton.core.util.TimeUtil
 
 class MeetingInactivityTrackerTests extends UnitSpec {
diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/GroupsChatTests.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/GroupsChatTests.scala
index ca600fa0a2c3bff3f0db4fb9d6a95797f61ae74d..60246a571a7341bd1abca9ce3c484d690e92168a 100755
--- a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/GroupsChatTests.scala
+++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/GroupsChatTests.scala
@@ -2,7 +2,6 @@ package org.bigbluebutton.core.models
 
 import org.bigbluebutton.common2.msgs.{ GroupChatAccess, GroupChatUser }
 import org.bigbluebutton.core.UnitSpec
-import org.bigbluebutton.core.domain.BbbSystemConst
 
 class GroupsChatTests extends UnitSpec {
 
@@ -10,7 +9,7 @@ class GroupsChatTests extends UnitSpec {
     val gcId = "gc-id"
     val chatName = "Public"
     val userId = "uid-1"
-    val createBy = GroupChatUser(BbbSystemConst.SYSTEM_USER, BbbSystemConst.SYSTEM_USER)
+    val createBy = GroupChatUser("groupId", "groupname")
     val gc = GroupChatFactory.create(gcId, chatName, GroupChatAccess.PUBLIC, createBy, Vector.empty, Vector.empty)
     val user = GroupChatUser(userId, "User 1")
     val gc2 = gc.add(user)
@@ -25,18 +24,16 @@ class GroupsChatTests extends UnitSpec {
   }
 
   "A GroupChat" should "be able to add, update, and remove msg" in {
-    val createBy = GroupChatUser(BbbSystemConst.SYSTEM_USER, BbbSystemConst.SYSTEM_USER)
+    val createBy = GroupChatUser("groupId", "groupname")
     val gcId = "gc-id"
     val chatName = "Public"
-    val userId = "uid-1"
     val gc = GroupChatFactory.create(gcId, chatName, GroupChatAccess.PUBLIC, createBy, Vector.empty, Vector.empty)
     val msgId1 = "msgid-1"
     val ts = System.currentTimeMillis()
     val hello = "Hello World!"
 
     val msg1 = GroupChatMessage(id = msgId1, timestamp = ts, correlationId = "cordId1", createdOn = ts,
-      updatedOn = ts, sender = createBy,
-      font = "arial", size = 12, color = "red", message = hello)
+      updatedOn = ts, sender = createBy, color = "red", message = hello)
     val gc2 = gc.add(msg1)
 
     assert(gc2.msgs.size == 1)
@@ -45,8 +42,7 @@ class GroupsChatTests extends UnitSpec {
     val foo = "Foo bar"
     val ts2 = System.currentTimeMillis()
     val msg2 = GroupChatMessage(id = msgId2, timestamp = ts2, correlationId = "cordId2", createdOn = ts2,
-      updatedOn = ts2, sender = createBy,
-      font = "arial", size = 12, color = "red", message = foo)
+      updatedOn = ts2, sender = createBy, color = "red", message = foo)
     val gc3 = gc2.add(msg2)
 
     assert(gc3.msgs.size == 2)
@@ -55,8 +51,7 @@ class GroupsChatTests extends UnitSpec {
     val msgId3 = "msgid-3"
     val ts3 = System.currentTimeMillis()
     val msg3 = GroupChatMessage(id = msgId3, timestamp = ts3, correlationId = "cordId3", createdOn = ts3,
-      updatedOn = ts3, sender = createBy,
-      font = "arial", size = 12, color = "red", message = baz)
+      updatedOn = ts3, sender = createBy, color = "red", message = baz)
     val gc4 = gc3.update(msg3)
 
     gc4.findMsgWithId(msgId3) match {
diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/pubsub/sender/ReceivedJsonMsgHandlerTraitTests.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/pubsub/sender/ReceivedJsonMsgHandlerTraitTests.scala
index 8de72a97a547dd9e08f8c75d76089b406df4574e..329383ad1512275c9afab734496cd35dfee05273 100755
--- a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/pubsub/sender/ReceivedJsonMsgHandlerTraitTests.scala
+++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/pubsub/sender/ReceivedJsonMsgHandlerTraitTests.scala
@@ -3,13 +3,13 @@ package org.bigbluebutton.core.pubsub.sender
 import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.core.{ AppsTestFixtures, UnitSpec }
-import org.bigbluebutton.core.bus.{ BbbMsgEvent, BbbMsgRouterEventBus, ReceivedJsonMessage }
+import org.bigbluebutton.core.bus.{ BbbMsgEvent, BbbMsgRouterEventBus }
 import org.bigbluebutton.core2.ReceivedMessageRouter
 import org.mockito.Mockito._
 import org.scalatest.mockito.MockitoSugar
 
 class ReceivedJsonMsgHandlerTraitTests extends UnitSpec
-    with AppsTestFixtures with MockitoSugar with SystemConfiguration {
+  with AppsTestFixtures with MockitoSugar with SystemConfiguration {
 
   class MessageRouter(val eventBus: BbbMsgRouterEventBus) extends ReceivedMessageRouter {
 
diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core2/testdata/TestDataGen.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core2/testdata/TestDataGen.scala
index d4789a43739f5a05ca2d49e1d5eb65c9a844e564..907d352379aec626bc70dbb139878d14d3d7b412 100755
--- a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core2/testdata/TestDataGen.scala
+++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core2/testdata/TestDataGen.scala
@@ -46,9 +46,9 @@ object TestDataGen {
   def createUserFor(liveMeeting: LiveMeeting, regUser: RegisteredUser, presenter: Boolean): UserState = {
     val u = UserState(intId = regUser.id, extId = regUser.externId, name = regUser.name, role = regUser.role,
       guest = regUser.guest, authed = regUser.authed, guestStatus = regUser.guestStatus,
-      emoji = "none", locked = false, presenter, avatar = regUser.avatarURL)
+      emoji = "none", locked = false, presenter = false, avatar = regUser.avatarURL, clientType = "unknown",
+      userLeftFlag = UserLeftFlag(false, 0))
     Users2x.add(liveMeeting.users2x, u)
-
     u
   }
 }
diff --git a/akka-bbb-fsesl/build.sbt b/akka-bbb-fsesl/build.sbt
index 319345d682c45b7255b457ba2a3adafae985b767..020426a651d37ecdf2f70f96a43d7518c3f52d8d 100755
--- a/akka-bbb-fsesl/build.sbt
+++ b/akka-bbb-fsesl/build.sbt
@@ -1,26 +1,35 @@
-enablePlugins(JavaServerAppPackaging)
-
-name := "bbb-fsesl-akka"
+import org.bigbluebutton.build._
 
-organization := "org.bigbluebutton"
+import scalariform.formatter.preferences._
+import com.typesafe.sbt.SbtScalariform
+import com.typesafe.sbt.SbtScalariform.ScalariformKeys
 
-version := "0.0.1"
+import com.typesafe.sbt.SbtNativePackager.autoImport._
 
-scalaVersion  := "2.12.6"
+enablePlugins(JavaServerAppPackaging)
 
-scalacOptions ++= Seq(
-  "-unchecked",
-  "-deprecation",
-  "-Xlint",
-  "-Ywarn-dead-code",
-  "-language:_",
-  "-target:jvm-1.8",
-  "-encoding", "UTF-8"
+version := "0.0.2"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
 )
 
 resolvers ++= Seq(
   "spray repo" at "http://repo.spray.io/",
-  "rediscala" at "http://dl.bintray.com/etaty/maven",
   "blindside-repos" at "http://blindside.googlecode.com/svn/repository/"
 )
 
@@ -37,63 +46,14 @@ testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console",
 
 testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
 
-val akkaVersion  = "2.5.14"
-val scalaTestV  = "2.2.6"
-
-
-libraryDependencies ++= {
-  Seq(
-    "ch.qos.logback"    	      %  "logback-classic"   % "1.2.3"       % "runtime",
-    "junit" 				      %  "junit"             % "4.11",
-    "commons-codec"             %  "commons-codec"     % "1.11",
-    "joda-time"                 %  "joda-time"         % "2.10",
-    "org.apache.commons"        %  "commons-lang3"     % "3.7"
-
-  )}
-
-libraryDependencies += "org.bigbluebutton" % "bbb-common-message_2.12" % "0.0.19-SNAPSHOT"
-
-libraryDependencies += "org.bigbluebutton"         %  "bbb-fsesl-client"   % "0.0.6"
-
-// https://mvnrepository.com/artifact/org.scala-lang/scala-library
-libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value
-// https://mvnrepository.com/artifact/org.scala-lang/scala-compiler
-libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-actor_2.12" % akkaVersion
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-slf4j_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-slf4j_2.12" % akkaVersion
-
-// https://mvnrepository.com/artifact/com.github.etaty/rediscala_2.12
-libraryDependencies += "com.github.etaty" % "rediscala_2.12" % "1.8.0"
-
-// For generating test reports
-libraryDependencies += "org.pegdown" % "pegdown" % "1.6.0" % "test"
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-testkit_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-testkit_2.12" % "2.5.14" % "test"
-
-// https://mvnrepository.com/artifact/org.scalactic/scalactic_2.12
-libraryDependencies += "org.scalactic" % "scalactic_2.12" % "3.0.5" % "test"
-
-// https://mvnrepository.com/artifact/org.scalatest/scalatest_2.12
-libraryDependencies += "org.scalatest" % "scalatest_2.12" % "3.0.5" % "test"
-
-libraryDependencies += "org.mockito" % "mockito-core" % "2.21.0" % "test"
-
-seq(Revolver.settings: _*)
-
-import com.typesafe.sbt.SbtScalariform
-
-import scalariform.formatter.preferences._
-import com.typesafe.sbt.SbtScalariform.ScalariformKeys
+Seq(Revolver.settings: _*)
+lazy val bbbFseslAkka = (project in file(".")).settings(name := "bbb-fsesl-akka", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
-SbtScalariform.defaultScalariformSettings
+scalariformAutoformat := false
 
-ScalariformKeys.preferences := ScalariformKeys.preferences.value
+scalariformPreferences := scalariformPreferences.value
   .setPreference(AlignSingleLineCaseStatements, true)
-  .setPreference(DoubleIndentClassDeclaration, true)
+  .setPreference(DoubleIndentConstructorArguments, true)
   .setPreference(AlignParameters, true)
 
 //-----------
@@ -121,16 +81,7 @@ daemonUser in Linux := user
 // group which will execute the application
 daemonGroup in Linux := group 
 
-mappings in Universal <+= (packageBin in Compile, sourceDirectory ) map { (_, src) =>
-    // Move the application.conf so the user can override settings here
-    val appConf = src / "main" / "resources" / "application.conf"
-    appConf -> "conf/application.conf"
-}
-
-mappings in Universal <+= (packageBin in Compile, sourceDirectory ) map { (_, src) =>
-    // Move logback.xml so the user can override settings here    
-    val logConf = src / "main" / "resources" / "logback.xml"
-    logConf -> "conf/logback.xml"
-}
+mappings in(Universal, packageBin) += file("src/main/resources/application.conf") -> "conf/application.conf"
+mappings in(Universal, packageBin) += file("src/main/resources/logback.xml") -> "conf/logback.xml"
 
 debianPackageDependencies in Debian ++= Seq("java8-runtime-headless", "bash")
diff --git a/akka-bbb-fsesl/project/Build.scala b/akka-bbb-fsesl/project/Build.scala
deleted file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/akka-bbb-fsesl/project/Dependencies.scala b/akka-bbb-fsesl/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6eab6d49d1aef1ed3e82de5be48f8e915e1f741b
--- /dev/null
+++ b/akka-bbb-fsesl/project/Dependencies.scala
@@ -0,0 +1,71 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+    val junitInterface = "0.11"
+    val scalactic = "3.0.3"
+
+    // Libraries
+    val akkaVersion = "2.5.17"
+    val logback = "1.2.3"
+
+    // Apache Commons
+    val lang = "3.8.1"
+    val codec = "1.11"
+
+    // BigBlueButton
+    val bbbCommons = "0.0.20-SNAPSHOT"
+    val bbbFsesl = "0.0.7-SNAPSHOT"
+
+    // Test
+    val scalaTest = "3.0.5"
+    val akkaTestKit = "2.5.18"
+    val junit = "4.12"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaCompiler = "org.scala-lang" % "scala-compiler" % Versions.scala
+
+    val akkaActor = "com.typesafe.akka" % "akka-actor_2.12" % Versions.akkaVersion
+    val akkaSl4fj = "com.typesafe.akka" % "akka-slf4j_2.12" % Versions.akkaVersion
+
+    val logback = "ch.qos.logback" % "logback-classic" % Versions.logback
+    val commonsCodec = "commons-codec" % "commons-codec" % Versions.codec
+
+    val apacheLang = "org.apache.commons" % "commons-lang3" % Versions.lang
+
+    val bbbCommons = "org.bigbluebutton" % "bbb-common-message_2.12" % Versions.bbbCommons
+    val bbbFseslClient = "org.bigbluebutton" % "bbb-fsesl-client" % Versions.bbbFsesl
+  }
+
+  object Test {
+    val scalaTest = "org.scalatest" %% "scalatest" % Versions.scalaTest % "test"
+    val junit = "junit" % "junit" % Versions.junit % "test"
+    val scalactic = "org.scalactic" % "scalactic_2.12" % Versions.scalactic % "test"
+    val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % Versions.akkaTestKit % "test"
+  }
+
+  val testing = Seq(
+    Test.scalaTest,
+    Test.junit,
+    Test.scalactic,
+    Test.akkaTestKit)
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaCompiler,
+    Compile.akkaActor,
+    Compile.akkaSl4fj,
+    Compile.logback,
+    Compile.commonsCodec,
+    Compile.apacheLang,
+    Compile.bbbCommons,
+    Compile.bbbFseslClient) ++ testing
+}
diff --git a/akka-bbb-fsesl/project/build.properties b/akka-bbb-fsesl/project/build.properties
index a6e117b61042ee81c62ba3a0fc5210d9502944df..2e6e3d24608ee15e892ed3b16d84224f7667e808 100755
--- a/akka-bbb-fsesl/project/build.properties
+++ b/akka-bbb-fsesl/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=1.2.6
\ No newline at end of file
diff --git a/akka-bbb-fsesl/project/plugins.sbt b/akka-bbb-fsesl/project/plugins.sbt
index 56e1e39f39dc0e78ca98f35d7c98f4c833509120..bc8c448553a2010f0c76ea69ccb7917f51ffef8a 100755
--- a/akka-bbb-fsesl/project/plugins.sbt
+++ b/akka-bbb-fsesl/project/plugins.sbt
@@ -1,11 +1,11 @@
 addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
-addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
-
 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")
+addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
+
+addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.12")
 
-addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
+addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.8")
 
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
diff --git a/akka-bbb-fsesl/run.sh b/akka-bbb-fsesl/run.sh
index 4015c4f1373a8caa1271bb9fa175c5940624bf89..97d3f3534508e5c4b3e816a8481bb4ae16b80644 100755
--- a/akka-bbb-fsesl/run.sh
+++ b/akka-bbb-fsesl/run.sh
@@ -1,3 +1 @@
-sbt clean
-sbt run
-
+sbt clean run
\ No newline at end of file
diff --git a/akka-bbb-fsesl/src/main/resources/application.conf b/akka-bbb-fsesl/src/main/resources/application.conf
index 37ac46cfee4c9c4a83c09df12747a5bbfeda6ac0..ac1acc3b350de7a5059eccf75d229db145a5a592 100755
--- a/akka-bbb-fsesl/src/main/resources/application.conf
+++ b/akka-bbb-fsesl/src/main/resources/application.conf
@@ -1,37 +1,37 @@
-akka {
-  actor {
-    debug {
-      receive = on
-    }
-  }
-  loggers = ["akka.event.slf4j.Slf4jLogger"]
-  loglevel = "DEBUG"
-  stdout-loglevel = "DEBUG"
-  
-    rediscala-subscriber-worker-dispatcher {
-      mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
-      # Throughput defines the maximum number of messages to be
-      # processed per actor before the thread jumps to the next actor.
-      # Set to 1 for as fair as possible.
-      throughput = 512
-    }
-}
-
-
-freeswitch {
-    esl {
-        host="127.0.0.1"
-        port=8021
-        password="ClueCon"
-    }
-    conf {
-    	profile="cdquality"
-    }
-}
-
-redis {
-    host="127.0.0.1"
-    port=6379
-    password=""
-}
-
+akka {
+  actor {
+    debug {
+      receive = on
+    }
+  }
+  loggers = ["akka.event.slf4j.Slf4jLogger"]
+  loglevel = "DEBUG"
+  stdout-loglevel = "DEBUG"
+  
+    redis-subscriber-worker-dispatcher {
+      mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
+      # Throughput defines the maximum number of messages to be
+      # processed per actor before the thread jumps to the next actor.
+      # Set to 1 for as fair as possible.
+      throughput = 512
+    }
+}
+
+
+freeswitch {
+    esl {
+        host="127.0.0.1"
+        port=8021
+        password="ClueCon"
+    }
+    conf {
+    	profile="cdquality"
+    }
+}
+
+redis {
+    host="127.0.0.1"
+    port=6379
+    password=""
+}
+
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/Boot.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/Boot.scala
index 1ab8664c2b09a3489ca5c8aa60322a67ca47f57e..aad91e4ddd34681322d68a2a89cf912849dbfb55 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/Boot.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/Boot.scala
@@ -1,19 +1,20 @@
 package org.bigbluebutton
 
-import akka.actor.{ ActorSystem }
-
-import org.bigbluebutton.endpoint.redis.{ AppsRedisSubscriberActor, RedisPublisher }
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
+import org.bigbluebutton.common2.redis.RedisPublisher
+import org.bigbluebutton.endpoint.redis.FSESLRedisSubscriberActor
 import org.bigbluebutton.freeswitch.{ RxJsonMsgHdlrActor, VoiceConferenceService }
-import org.bigbluebutton.freeswitch.bus.InsonMsgBus
 import org.bigbluebutton.freeswitch.voice.FreeswitchConferenceEventListener
 import org.bigbluebutton.freeswitch.voice.freeswitch.{ ConnectionManager, ESLEventListener, FreeswitchApplication }
 import org.freeswitch.esl.client.manager.DefaultManagerConnection
 
+import akka.actor.ActorSystem
+
 object Boot extends App with SystemConfiguration {
 
   implicit val system = ActorSystem("bigbluebutton-fsesl-system")
 
-  val redisPublisher = new RedisPublisher(system)
+  val redisPublisher = new RedisPublisher(system, "BbbFsEslAkkaPub")
 
   val eslConnection = new DefaultManagerConnection(eslHost, eslPort, eslPassword)
 
@@ -30,10 +31,9 @@ object Boot extends App with SystemConfiguration {
   val fsApplication = new FreeswitchApplication(connManager, fsProfile)
   fsApplication.start()
 
-  val inJsonMsgBus = new InsonMsgBus
+  val inJsonMsgBus = new IncomingJsonMessageBus
   val redisMessageHandlerActor = system.actorOf(RxJsonMsgHdlrActor.props(fsApplication))
   inJsonMsgBus.subscribe(redisMessageHandlerActor, toFsAppsJsonChannel)
 
-  val redisSubscriberActor = system.actorOf(AppsRedisSubscriberActor.props(system, inJsonMsgBus), "redis-subscriber")
-
+  val redisSubscriberActor = system.actorOf(FSESLRedisSubscriberActor.props(system, inJsonMsgBus), "redis-subscriber")
 }
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
index c9c776a410d714d2e28627a173e97a075500050e..188d202835c68438d44ba8fc7f26308fb929d5d2 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
@@ -1,23 +1,15 @@
 package org.bigbluebutton
 
-import com.typesafe.config.ConfigFactory
 import scala.util.Try
 
-trait SystemConfiguration {
-
-  val config = ConfigFactory.load()
+import org.bigbluebutton.common2.redis.RedisConfiguration
 
+trait SystemConfiguration extends RedisConfiguration {
   lazy val eslHost = Try(config.getString("freeswitch.esl.host")).getOrElse("127.0.0.1")
   lazy val eslPort = Try(config.getInt("freeswitch.esl.port")).getOrElse(8021)
   lazy val eslPassword = Try(config.getString("freeswitch.esl.password")).getOrElse("ClueCon")
   lazy val fsProfile = Try(config.getString("freeswitch.conf.profile")).getOrElse("cdquality")
 
-  lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
-  lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
-  lazy val redisPassword = Try(config.getString("redis.password")).getOrElse("")
-
-  lazy val toVoiceConfRedisChannel = Try(config.getString("redis.toVoiceConfRedisChannel")).getOrElse("to-voice-conf-redis-channel")
-  lazy val fromVoiceConfRedisChannel = Try(config.getString("redis.fromVoiceConfRedisChannel")).getOrElse("from-voice-conf-redis-channel")
   lazy val toFsAppsJsonChannel = Try(config.getString("eventBus.toFsAppsChannel")).getOrElse("to-fs-apps-json-channel")
   lazy val fromFsAppsJsonChannel = Try(config.getString("eventBus.fromFsAppsChannel")).getOrElse("from-fs-apps-json-channel")
 }
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala
deleted file mode 100755
index 4f969be0b6465347544e038f95917fa3c8a1794e..0000000000000000000000000000000000000000
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bigbluebutton.endpoint.redis
-
-import java.io.PrintWriter
-import java.io.StringWriter
-import java.net.InetSocketAddress
-
-import scala.concurrent.ExecutionContext.Implicits.global
-import scala.concurrent.duration.DurationInt
-import org.bigbluebutton.SystemConfiguration
-import akka.actor.ActorSystem
-import akka.actor.OneForOneStrategy
-import akka.actor.Props
-import akka.actor.SupervisorStrategy.Resume
-import org.bigbluebutton.freeswitch.bus.{ InJsonMsg, InsonMsgBus, ReceivedJsonMsg }
-import redis.actors.RedisSubscriberActor
-import redis.api.pubsub.Message
-import redis.api.pubsub.PMessage
-import redis.api.servers.ClientSetname
-
-object AppsRedisSubscriberActor extends SystemConfiguration {
-
-  val channels = Seq(toVoiceConfRedisChannel)
-  val patterns = Seq("bigbluebutton:to-voice-conf:*", "bigbluebutton:from-bbb-apps:*")
-
-  def props(system: ActorSystem, inJsonMgBus: InsonMsgBus): Props =
-    Props(classOf[AppsRedisSubscriberActor], system, inJsonMgBus,
-      redisHost, redisPort,
-      channels, patterns).withDispatcher("akka.rediscala-subscriber-worker-dispatcher")
-}
-
-class AppsRedisSubscriberActor(
-  val system:  ActorSystem,
-  inJsonMgBus: InsonMsgBus, redisHost: String,
-  redisPort: Int,
-  channels:  Seq[String] = Nil, patterns: Seq[String] = Nil)
-    extends RedisSubscriberActor(
-      new InetSocketAddress(redisHost, redisPort),
-      channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") }) with SystemConfiguration {
-
-  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
-    case e: Exception => {
-      val sw: StringWriter = new StringWriter()
-      sw.write("An exception has been thrown on AppsRedisSubscriberActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
-      e.printStackTrace(new PrintWriter(sw))
-      log.error(sw.toString())
-      Resume
-    }
-  }
-
-  //  val decoder = new FromJsonDecoder()
-
-  var lastPongReceivedOn = 0L
-  system.scheduler.schedule(10 seconds, 10 seconds)(checkPongMessage())
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  write(ClientSetname("BbbFsEslAkkaSub").encodedRequest)
-
-  def checkPongMessage() {
-    val now = System.currentTimeMillis()
-
-    if (lastPongReceivedOn != 0 && (now - lastPongReceivedOn > 30000)) {
-      log.error("FSESL pubsub error!");
-    }
-  }
-
-  def onMessage(message: Message) {
-    if (message.channel == toVoiceConfRedisChannel) {
-      val receivedJsonMessage = new ReceivedJsonMsg(message.channel, message.data.utf8String)
-      log.debug(s"RECEIVED:\n [${receivedJsonMessage.channel}] \n ${receivedJsonMessage.data} \n")
-      inJsonMgBus.publish(InJsonMsg(toFsAppsJsonChannel, receivedJsonMessage))
-    }
-  }
-
-  def onPMessage(pmessage: PMessage) {
-    //    log.debug(s"pattern message received: $pmessage")
-  }
-
-  def handleMessage(msg: String) {
-    log.warning("**** TODO: Handle pubsub messages. ****")
-  }
-}
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/FSESLRedisSubscriberActor.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/FSESLRedisSubscriberActor.scala
new file mode 100755
index 0000000000000000000000000000000000000000..016bc9890b42407769b824287b1705f415063b9e
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/FSESLRedisSubscriberActor.scala
@@ -0,0 +1,46 @@
+package org.bigbluebutton.endpoint.redis
+
+import scala.concurrent.ExecutionContext.Implicits.global
+import scala.concurrent.duration.DurationInt
+
+import org.bigbluebutton.SystemConfiguration
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
+import org.bigbluebutton.common2.redis.{ RedisSubscriber, RedisSubscriberProvider }
+
+import akka.actor.ActorSystem
+import akka.actor.Props
+
+object FSESLRedisSubscriberActor extends RedisSubscriber {
+
+  val channels = Seq(toVoiceConfRedisChannel)
+  val patterns = Seq("bigbluebutton:to-voice-conf:*", "bigbluebutton:from-bbb-apps:*")
+
+  def props(system: ActorSystem, inJsonMgBus: IncomingJsonMessageBus): Props =
+    Props(
+      classOf[FSESLRedisSubscriberActor],
+      system, inJsonMgBus,
+      redisHost, redisPort,
+      channels, patterns).withDispatcher("akka.redis-subscriber-worker-dispatcher")
+}
+
+class FSESLRedisSubscriberActor(
+  system:      ActorSystem,
+  inJsonMgBus: IncomingJsonMessageBus,
+  redisHost:   String, redisPort: Int,
+  channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
+  extends RedisSubscriberProvider(system, "BbbFsEslAkkaSub", channels, patterns, inJsonMgBus) with SystemConfiguration {
+
+  var lastPongReceivedOn = 0L
+  system.scheduler.schedule(10 seconds, 10 seconds)(checkPongMessage())
+
+  def checkPongMessage() {
+    val now = System.currentTimeMillis()
+
+    if (lastPongReceivedOn != 0 && (now - lastPongReceivedOn > 30000)) {
+      log.error("FSESL pubsub error!");
+    }
+  }
+
+  addListener(toFsAppsJsonChannel)
+  subscribe()
+}
\ No newline at end of file
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/RedisPublisher.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/RedisPublisher.scala
deleted file mode 100755
index 11acf3d06d30cd2574e3e38a26befc09fae7166d..0000000000000000000000000000000000000000
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/RedisPublisher.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bigbluebutton.endpoint.redis
-
-import redis.RedisClient
-import akka.actor.ActorSystem
-import org.bigbluebutton.SystemConfiguration
-
-class RedisPublisher(val system: ActorSystem) extends SystemConfiguration {
-
-  val redis = RedisClient(redisHost, redisPort)(system)
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  redis.clientSetname("BbbFsEslAkkaPub")
-
-  def publish(channel: String, data: String) {
-    //println("PUBLISH TO [" + channel + "]: \n [" + data + "]")
-    redis.publish(channel, data)
-  }
-
-}
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgHdlrActor.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgHdlrActor.scala
index 378210c50ca7307ba0927d0d84fc0f18997471ee..dc839a9f3162c165c0ec3521fd1fa0a931147fd3 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgHdlrActor.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgHdlrActor.scala
@@ -1,12 +1,16 @@
 package org.bigbluebutton.freeswitch
 
-import akka.actor.{ Actor, ActorLogging, Props }
-import com.fasterxml.jackson.databind.JsonNode
 import org.bigbluebutton.SystemConfiguration
+import org.bigbluebutton.common2.bus.ReceivedJsonMessage
 import org.bigbluebutton.common2.msgs._
-import org.bigbluebutton.freeswitch.bus.ReceivedJsonMsg
 import org.bigbluebutton.freeswitch.voice.freeswitch.FreeswitchApplication
 
+import com.fasterxml.jackson.databind.JsonNode
+
+import akka.actor.Actor
+import akka.actor.ActorLogging
+import akka.actor.Props
+
 object RxJsonMsgHdlrActor {
   def props(fsApp: FreeswitchApplication): Props =
     Props(classOf[RxJsonMsgHdlrActor], fsApp)
@@ -15,13 +19,13 @@ object RxJsonMsgHdlrActor {
 class RxJsonMsgHdlrActor(val fsApp: FreeswitchApplication) extends Actor with ActorLogging
     with SystemConfiguration with RxJsonMsgDeserializer {
   def receive = {
-    case msg: ReceivedJsonMsg =>
+    case msg: ReceivedJsonMessage =>
       log.debug("handling {} - {}", msg.channel, msg.data)
       handleReceivedJsonMessage(msg)
     case _ => // do nothing
   }
 
-  def handleReceivedJsonMessage(msg: ReceivedJsonMsg): Unit = {
+  def handleReceivedJsonMessage(msg: ReceivedJsonMessage): Unit = {
     for {
       envJsonNode <- JsonDeserializer.toBbbCommonEnvJsNodeMsg(msg.data)
     } yield handle(envJsonNode.envelope, envJsonNode.core)
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
index f82d08080087570a5b1102f2e972443904c10163..a72302e7f3fdbbd6093f8d7c206668e7fe251aca 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
@@ -2,9 +2,9 @@ package org.bigbluebutton.freeswitch
 
 import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.freeswitch.voice.IVoiceConferenceService
-import org.bigbluebutton.endpoint.redis.RedisPublisher
 import org.bigbluebutton.common2.msgs._
-import org.bigbluebutton.common2.util.JsonUtil
+import org.bigbluebutton.common2.util.JsonUtil
+import org.bigbluebutton.common2.redis.RedisPublisher
 
 class VoiceConferenceService(sender: RedisPublisher) extends IVoiceConferenceService with SystemConfiguration {
 
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/bus/InJsonMsgBus.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/bus/InJsonMsgBus.scala
deleted file mode 100755
index 6f7bb865ea8c1002d7f6ff16655a3c2eb016568e..0000000000000000000000000000000000000000
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/bus/InJsonMsgBus.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bigbluebutton.freeswitch.bus
-
-import akka.actor.ActorRef
-import akka.event.{ EventBus, LookupClassification }
-
-case class ReceivedJsonMsg(channel: String, data: String)
-case class InJsonMsg(val topic: String, val payload: ReceivedJsonMsg)
-
-class InsonMsgBus extends EventBus with LookupClassification {
-  type Event = InJsonMsg
-  type Classifier = String
-  type Subscriber = ActorRef
-
-  // is used for extracting the classifier from the incoming events
-  override protected def classify(event: Event): Classifier = event.topic
-
-  // will be invoked for each event for all subscribers which registered themselves
-  // for the event’s classifier
-  override protected def publish(event: Event, subscriber: Subscriber): Unit = {
-    subscriber ! event.payload
-  }
-
-  // must define a full order over the subscribers, expressed as expected from
-  // `java.lang.Comparable.compare`
-  override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
-    a.compareTo(b)
-
-  // determines the initial size of the index data structure
-  // used internally (i.e. the expected number of different classifiers)
-  override protected def mapSize: Int = 128
-}
diff --git a/bbb-apps-common/build.sbt b/bbb-apps-common/build.sbt
index 693e0e360cde0a9ce16593b4d235f9a6e0d9eb10..9a31293e2a7201ccbe2e0c514da9c4b7a4ac3c33 100755
--- a/bbb-apps-common/build.sbt
+++ b/bbb-apps-common/build.sbt
@@ -1,20 +1,23 @@
-
-name := "bbb-apps-common"
-
-organization := "org.bigbluebutton"
-
-version := "0.0.3-SNAPSHOT"
-
-scalaVersion  := "2.12.6"
-
-scalacOptions ++= Seq(
-  "-unchecked",
-  "-deprecation",
-  "-Xlint",
-  "-Ywarn-dead-code",
-  "-language:_",
-  "-target:jvm-1.8",
-  "-encoding", "UTF-8"
+import org.bigbluebutton.build._
+
+version := "0.0.4-SNAPSHOT"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
 )
 
 // We want to have our jar files in lib_managed dir.
@@ -22,57 +25,8 @@ scalacOptions ++= Seq(
 // into eclipse.
 retrieveManaged := true
 
-testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console", "junitxml")
-
-testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
-
-val akkaVersion  = "2.5.14"
-val scalaTestV  = "2.2.6"
-
-// https://mvnrepository.com/artifact/org.scala-lang/scala-library
-libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value
-// https://mvnrepository.com/artifact/org.scala-lang/scala-compiler
-libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-actor_2.12" % "2.5.1"
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-slf4j_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-slf4j_2.12" % "2.5.1"
-
-// https://mvnrepository.com/artifact/com.github.etaty/rediscala_2.12
-libraryDependencies += "com.github.etaty" % "rediscala_2.12" % "1.8.0"
-
-libraryDependencies += "com.softwaremill.quicklens" %% "quicklens" % "1.4.11"
-
-libraryDependencies += "org.bigbluebutton" % "bbb-common-message_2.12" % "0.0.19-SNAPSHOT"
-
-libraryDependencies += "com.google.code.gson" % "gson" % "2.8.5"
-libraryDependencies += "redis.clients" % "jedis" % "2.9.0"
-
-// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
-libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.7"
-libraryDependencies += "commons-io" % "commons-io" % "2.4"
-libraryDependencies += "org.apache.commons" % "commons-pool2" % "2.6.0"
-libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.23" % "provided"
-
-
-libraryDependencies += "junit" % "junit" % "4.12" % "test"
-libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
-
-// For generating test reports
-libraryDependencies += "org.pegdown" % "pegdown" % "1.6.0" % "test"
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-testkit_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-testkit_2.12" % "2.5.1" % "test"
-
-// https://mvnrepository.com/artifact/org.scalactic/scalactic_2.12
-libraryDependencies += "org.scalactic" % "scalactic_2.12" % "3.0.3" % "test"
-
-// https://mvnrepository.com/artifact/org.scalatest/scalatest_2.12
-libraryDependencies += "org.scalatest" % "scalatest_2.12" % "3.0.3" % "test"
-
-libraryDependencies += "org.mockito" % "mockito-core" % "2.7.22" % "test"
-
-seq(Revolver.settings: _*)
+Seq(Revolver.settings: _*)
+lazy val appsCommons = (project in file(".")).settings(name := "bbb-apps-common", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
 //-----------
 // Packaging
@@ -133,5 +87,3 @@ pomExtra := (
 licenses := Seq("LGPL-3.0" -> url("http://opensource.org/licenses/LGPL-3.0"))
 
 homepage := Some(url("http://www.bigbluebutton.org"))
-  
-
diff --git a/bbb-apps-common/deploy.sh b/bbb-apps-common/deploy.sh
index ccba754eaaf8182e665e94d1210571e23ebfb7b4..f829bc13dc598da480ee4e512a87c9436925a359 100755
--- a/bbb-apps-common/deploy.sh
+++ b/bbb-apps-common/deploy.sh
@@ -1,2 +1 @@
-sbt clean
-sbt publish publishLocal
+sbt clean publish publishLocal
diff --git a/bbb-apps-common/project/Dependencies.scala b/bbb-apps-common/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..86f51a25ef7c86fa3e7f0a0f0a11c094d9bbf46d
--- /dev/null
+++ b/bbb-apps-common/project/Dependencies.scala
@@ -0,0 +1,57 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+
+    // Libraries
+    val akkaVersion = "2.5.17"
+    val gson = "2.8.5"
+    val sl4j = "1.7.25"
+    val quicklens = "1.4.11"
+
+    // Apache Commons
+    val lang = "3.8.1"
+    val io = "2.6"
+    val pool = "2.6.0"
+
+    // BigBlueButton
+    val bbbCommons = "0.0.20-SNAPSHOT"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaCompiler = "org.scala-lang" % "scala-compiler" % Versions.scala
+
+    val akkaActor = "com.typesafe.akka" % "akka-actor_2.12" % Versions.akkaVersion
+    val akkaSl4fj = "com.typesafe.akka" % "akka-slf4j_2.12" % Versions.akkaVersion
+
+    val googleGson = "com.google.code.gson" % "gson" % Versions.gson
+    val quicklens = "com.softwaremill.quicklens" %% "quicklens" % Versions.quicklens
+    val sl4jApi = "org.slf4j" % "slf4j-api" % Versions.sl4j % "provided"
+
+    val apacheLang = "org.apache.commons" % "commons-lang3" % Versions.lang
+    val apacheIo = "commons-io" % "commons-io" % Versions.io
+    val apachePool2 = "org.apache.commons" % "commons-pool2" % Versions.pool
+
+    val bbbCommons = "org.bigbluebutton" % "bbb-common-message_2.12" % Versions.bbbCommons
+  }
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaCompiler,
+    Compile.akkaActor,
+    Compile.akkaSl4fj,
+    Compile.googleGson,
+    Compile.quicklens,
+    Compile.sl4jApi,
+    Compile.apacheLang,
+    Compile.apacheIo,
+    Compile.apachePool2,
+    Compile.bbbCommons)
+}
diff --git a/bbb-apps-common/project/build.properties b/bbb-apps-common/project/build.properties
index a6e117b61042ee81c62ba3a0fc5210d9502944df..2e6e3d24608ee15e892ed3b16d84224f7667e808 100755
--- a/bbb-apps-common/project/build.properties
+++ b/bbb-apps-common/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=1.2.6
\ No newline at end of file
diff --git a/bbb-apps-common/project/plugins.sbt b/bbb-apps-common/project/plugins.sbt
index 1a99bbcaf45749dbd833d7f6141744e2062bb181..3559bf68d62ef19f25fa810533bbe596eb022d02 100755
--- a/bbb-apps-common/project/plugins.sbt
+++ b/bbb-apps-common/project/plugins.sbt
@@ -1,9 +1,9 @@
-addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.2")
+addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
-addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.2.0")
+addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
+addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1")
 
-addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
+addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.8")
 
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ClientGWApplication.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ClientGWApplication.scala
index 9f0bf267da240b1da0d28ae1f8231cfed4f00891..bad84e615018bd9a435aad7f8f63a3f95855270d 100644
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ClientGWApplication.scala
+++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ClientGWApplication.scala
@@ -3,12 +3,16 @@ package org.bigbluebutton.client
 import akka.actor.ActorSystem
 import akka.event.Logging
 import org.bigbluebutton.client.bus._
-import org.bigbluebutton.client.endpoint.redis.{AppsRedisSubscriberActor, MessageSender, RedisPublisher}
+import org.bigbluebutton.client.endpoint.redis.Red5AppsRedisSubscriberActor
 import org.bigbluebutton.client.meeting.MeetingManagerActor
+import org.bigbluebutton.common2.redis.RedisPublisher
 
 import scala.concurrent.duration._
+import org.bigbluebutton.common2.redis.MessageSender
+import org.bigbluebutton.api2.bus.MsgFromAkkaAppsEventBus
+import org.bigbluebutton.common2.bus.JsonMsgFromAkkaAppsBus
 
-class ClientGWApplication(val msgToClientGW: MsgToClientGW) extends SystemConfiguration{
+class ClientGWApplication(val msgToClientGW: MsgToClientGW) extends SystemConfiguration {
 
   implicit val system = ActorSystem("bbb-apps-common")
   implicit val timeout = akka.util.Timeout(3 seconds)
@@ -20,7 +24,7 @@ class ClientGWApplication(val msgToClientGW: MsgToClientGW) extends SystemConfig
   private val msgToRedisEventBus = new MsgToRedisEventBus
   private val msgToClientEventBus = new MsgToClientEventBus
 
-  private val redisPublisher = new RedisPublisher(system)
+  private val redisPublisher = new RedisPublisher(system, "Red5AppsPub")
   private val msgSender: MessageSender = new MessageSender(redisPublisher)
 
   private val meetingManagerActorRef = system.actorOf(
@@ -41,19 +45,17 @@ class ClientGWApplication(val msgToClientGW: MsgToClientGW) extends SystemConfig
 
   msgToClientEventBus.subscribe(msgToClientJsonActor, toClientChannel)
 
-  private val appsRedisSubscriberActor = system.actorOf(
-    AppsRedisSubscriberActor.props(receivedJsonMsgBus), "appsRedisSubscriberActor")
+  private val appsRedisSubscriberActor = system.actorOf(Red5AppsRedisSubscriberActor.props(system, receivedJsonMsgBus), "appsRedisSubscriberActor")
 
   private val receivedJsonMsgHdlrActor = system.actorOf(
     ReceivedJsonMsgHdlrActor.props(msgFromAkkaAppsEventBus), "receivedJsonMsgHdlrActor")
 
   receivedJsonMsgBus.subscribe(receivedJsonMsgHdlrActor, fromAkkaAppsJsonChannel)
 
-
   /**
-    *
-    * External Interface for Gateway
-    */
+   *
+   * External Interface for Gateway
+   */
 
   def connect(connInfo: ConnInfo): Unit = {
     //log.debug("**** ClientGWApplication connect " + connInfo)
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/MsgToRedisActor.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/MsgToRedisActor.scala
index 94b37ae92489caf176caa2a5b3191dbaeb4d3fd4..5a3ce496ff2c1827b741c8106adf66693af2f2c1 100644
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/MsgToRedisActor.scala
+++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/MsgToRedisActor.scala
@@ -1,10 +1,10 @@
 package org.bigbluebutton.client
 
-import akka.actor.{Actor, ActorLogging, Props}
+import akka.actor.{ Actor, ActorLogging, Props }
 import org.bigbluebutton.common2.msgs.BbbCommonEnvJsNodeMsg
-import org.bigbluebutton.common2.util.JsonUtil
-import org.bigbluebutton.client.endpoint.redis.MessageSender
+import org.bigbluebutton.common2.util.JsonUtil
 import org.bigbluebutton.common2.msgs.LookUpUserReqMsg
+import org.bigbluebutton.common2.redis.MessageSender
 
 object MsgToRedisActor {
   def props(msgSender: MessageSender): Props =
@@ -20,11 +20,10 @@ class MsgToRedisActor(msgSender: MessageSender)
 
   def handle(msg: BbbCommonEnvJsNodeMsg): Unit = {
     val json = JsonUtil.toJson(msg)
-    
+
     msg.envelope.name match {
       case LookUpUserReqMsg.NAME => msgSender.send(toThirdPartyRedisChannel, json)
-      case _ => msgSender.send(toAkkaAppsRedisChannel, json)
+      case _                     => msgSender.send(toAkkaAppsRedisChannel, json)
     }
   }
-
 }
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedJsonMsgHdlrActor.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedJsonMsgHdlrActor.scala
index d18cb333ed7e2cbd1066db5c11e61bf3e50160e8..ea6c3a3b660418de17a5c7969212f142d6f9e95e 100755
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedJsonMsgHdlrActor.scala
+++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedJsonMsgHdlrActor.scala
@@ -1,11 +1,13 @@
 package org.bigbluebutton.client
 
 import akka.actor.{Actor, ActorLogging, Props}
-import org.bigbluebutton.client.bus.{JsonMsgFromAkkaApps, MsgFromAkkaApps, MsgFromAkkaAppsEventBus}
 import org.bigbluebutton.common2.msgs.BbbCommonEnvJsNodeMsg
 import org.bigbluebutton.common2.util.JsonUtil
 
-import scala.util.{Failure, Success}
+import scala.util.{Failure, Success}
+import org.bigbluebutton.common2.bus.JsonMsgFromAkkaApps
+import org.bigbluebutton.api2.bus.MsgFromAkkaAppsEventBus
+import org.bigbluebutton.api2.bus.MsgFromAkkaApps
 
 
 object ReceivedJsonMsgHdlrActor {
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedMessageRouter.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedMessageRouter.scala
index 701be0b1654e89eb0a0d7b7cad51305b7b72be7d..232720efbf4c61140f6ec0d5ddfe963e189cfd27 100755
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedMessageRouter.scala
+++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/ReceivedMessageRouter.scala
@@ -1,6 +1,6 @@
-package org.bigbluebutton.client
-
-import org.bigbluebutton.client.bus.{MsgFromAkkaApps, MsgFromAkkaAppsEventBus}
+package org.bigbluebutton.client
+
+import org.bigbluebutton.api2.bus.{ MsgFromAkkaApps, MsgFromAkkaAppsEventBus }
 
 trait ReceivedMessageRouter {
   val msgFromAkkaAppsEventBus: MsgFromAkkaAppsEventBus
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/SystemConfiguration.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/SystemConfiguration.scala
index 26e7528bbbb99e0b0424c9ca0e269c0cde477089..0f9d34cfadcaa854d871330a1434928744281ebd 100644
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/SystemConfiguration.scala
+++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/SystemConfiguration.scala
@@ -1,17 +1,10 @@
 package org.bigbluebutton.client
 
 import scala.util.Try
-import com.typesafe.config.ConfigFactory
 
-trait SystemConfiguration {
-  val config = ConfigFactory.load()
+import org.bigbluebutton.common2.redis.RedisConfiguration
 
-  lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
-  lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
-  lazy val redisPassword = Try(config.getString("redis.password")).getOrElse("")
-
-  lazy val toAkkaAppsRedisChannel = Try(config.getString("redis.toAkkaAppsRedisChannel")).getOrElse("to-akka-apps-redis-channel")
-  lazy val fromAkkaAppsRedisChannel = Try(config.getString("redis.fromAkkaAppsRedisChannel")).getOrElse("from-akka-apps-redis-channel")
+trait SystemConfiguration extends RedisConfiguration {
   lazy val toThirdPartyRedisChannel = Try(config.getString("redis.toThirdPartyRedisChannel")).getOrElse("to-third-party-redis-channel")
   lazy val fromThirdPartyRedisChannel = Try(config.getString("redis.fromThirdPartyRedisChannel")).getOrElse("from-third-party-redis-channel")
   lazy val fromAkkaAppsChannel = Try(config.getString("eventBus.fromAkkaAppsChannel")).getOrElse("from-akka-apps-channel")
@@ -19,8 +12,4 @@ trait SystemConfiguration {
   lazy val fromClientChannel = Try(config.getString("eventBus.fromClientChannel")).getOrElse("from-client-channel")
   lazy val toClientChannel = Try(config.getString("eventBus.toClientChannel")).getOrElse("to-client-channel")
   lazy val fromAkkaAppsJsonChannel = Try(config.getString("eventBus.fromAkkaAppsChannel")).getOrElse("from-akka-apps-json-channel")
-
-  lazy val fromAkkaAppsWbRedisChannel = Try(config.getString("redis.fromAkkaAppsWbRedisChannel")).getOrElse("from-akka-apps-wb-redis-channel")
-  lazy val fromAkkaAppsChatRedisChannel = Try(config.getString("redis.fromAkkaAppsChatRedisChannel")).getOrElse("from-akka-apps-chat-redis-channel")
-  lazy val fromAkkaAppsPresRedisChannel = Try(config.getString("redis.fromAkkaAppsPresRedisChannel")).getOrElse("from-akka-apps-pres-redis-channel")
 }
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/bus/JsonMsgFromAkkaAppsBus.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/bus/JsonMsgFromAkkaAppsBus.scala
deleted file mode 100755
index ad28aa0618eb0ce5298feb8be9383ff2850d4c5c..0000000000000000000000000000000000000000
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/bus/JsonMsgFromAkkaAppsBus.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bigbluebutton.client.bus
-
-import akka.actor.ActorRef
-import akka.event.{EventBus, LookupClassification}
-
-case class JsonMsgFromAkkaApps(name: String, data: String)
-case class JsonMsgFromAkkaAppsEvent(val topic: String, val payload: JsonMsgFromAkkaApps)
-
-class JsonMsgFromAkkaAppsBus extends EventBus with LookupClassification {
-  type Event = JsonMsgFromAkkaAppsEvent
-  type Classifier = String
-  type Subscriber = ActorRef
-
-  // is used for extracting the classifier from the incoming events
-  override protected def classify(event: Event): Classifier = event.topic
-
-  // will be invoked for each event for all subscribers which registered themselves
-  // for the event’s classifier
-  override protected def publish(event: Event, subscriber: Subscriber): Unit = {
-    subscriber ! event.payload
-  }
-
-  // must define a full order over the subscribers, expressed as expected from
-  // `java.lang.Comparable.compare`
-  override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
-  a.compareTo(b)
-
-  // determines the initial size of the index data structure
-  // used internally (i.e. the expected number of different classifiers)
-  override protected def mapSize: Int = 128
-
-}
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/bus/MsgFromAkkaAppsEventBus.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/bus/MsgFromAkkaAppsEventBus.scala
deleted file mode 100755
index 20dc5055368e2084c2f8c3dc50e6fcf88f870135..0000000000000000000000000000000000000000
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/bus/MsgFromAkkaAppsEventBus.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bigbluebutton.client.bus
-
-import akka.actor.ActorRef
-import akka.event.{EventBus, LookupClassification}
-import org.bigbluebutton.common2.msgs.{ BbbCommonEnvJsNodeMsg}
-
-case class MsgFromAkkaApps(val topic: String, val payload: BbbCommonEnvJsNodeMsg)
-
-class MsgFromAkkaAppsEventBus extends EventBus with LookupClassification {
-  type Event = MsgFromAkkaApps
-  type Classifier = String
-  type Subscriber = ActorRef
-
-  // is used for extracting the classifier from the incoming events
-  override protected def classify(event: Event): Classifier = event.topic
-
-  // will be invoked for each event for all subscribers which registered themselves
-  // for the event’s classifier
-  override protected def publish(event: Event, subscriber: Subscriber): Unit = {
-    subscriber ! event.payload
-  }
-
-  // must define a full order over the subscribers, expressed as expected from
-  // `java.lang.Comparable.compare`
-  override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
-  a.compareTo(b)
-
-  // determines the initial size of the index data structure
-  // used internally (i.e. the expected number of different classifiers)
-  override protected def mapSize: Int = 128
-}
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/AppsRedisSubscriberActor.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/AppsRedisSubscriberActor.scala
deleted file mode 100644
index 2d3a30fe97fac898b5d91ae743c4c096d5c67658..0000000000000000000000000000000000000000
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/AppsRedisSubscriberActor.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bigbluebutton.client.endpoint.redis
-
-import akka.actor.{ActorLogging, OneForOneStrategy, Props}
-import akka.actor.SupervisorStrategy.Resume
-import java.io.{PrintWriter, StringWriter}
-import java.net.InetSocketAddress
-
-import redis.actors.RedisSubscriberActor
-import redis.api.pubsub.{Message, PMessage}
-
-import scala.concurrent.duration._
-import org.bigbluebutton.client._
-import org.bigbluebutton.client.bus.{JsonMsgFromAkkaApps, JsonMsgFromAkkaAppsBus, JsonMsgFromAkkaAppsEvent}
-import redis.api.servers.ClientSetname
-
-object AppsRedisSubscriberActor extends SystemConfiguration {
-
-  val channels = Seq(fromAkkaAppsRedisChannel, fromAkkaAppsWbRedisChannel, fromAkkaAppsChatRedisChannel, fromAkkaAppsPresRedisChannel, fromThirdPartyRedisChannel)
-  val patterns = Seq("bigbluebutton:from-bbb-apps:*")
-
-  def props(jsonMsgBus: JsonMsgFromAkkaAppsBus): Props =
-    Props(classOf[AppsRedisSubscriberActor], jsonMsgBus,
-      redisHost, redisPort,
-      channels, patterns).withDispatcher("akka.rediscala-subscriber-worker-dispatcher")
-}
-
-class AppsRedisSubscriberActor(jsonMsgBus: JsonMsgFromAkkaAppsBus, redisHost: String,
-                               redisPort: Int,
-                               channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
-    extends RedisSubscriberActor(new InetSocketAddress(redisHost, redisPort),
-      channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") })
-      with SystemConfiguration with ActorLogging {
-
-  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
-    case e: Exception => {
-      val sw: StringWriter = new StringWriter()
-      sw.write("An exception has been thrown on AppsRedisSubscriberActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
-      e.printStackTrace(new PrintWriter(sw))
-      log.error(sw.toString())
-      Resume
-    }
-  }
-
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  write(ClientSetname("Red5AppsSub").encodedRequest)
-
-  def onMessage(message: Message) {
-    if (channels.contains(message.channel)) {
-      //log.debug(s"RECEIVED:\n ${message.data.utf8String} \n")
-      val receivedJsonMessage = new JsonMsgFromAkkaApps(message.channel, message.data.utf8String)
-      jsonMsgBus.publish(JsonMsgFromAkkaAppsEvent(fromAkkaAppsJsonChannel, receivedJsonMessage))
-    }
-
-  }
-
-  def onPMessage(pmessage: PMessage) {
-    // We don't use PSubscribe anymore, but an implementation of the method is required
-    log.error("Should not be receiving a PMessage. It triggered on a match of pattern: " + pmessage.patternMatched)
-  }
-}
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/KeepAliveRedisPublisher.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/KeepAliveRedisPublisher.scala
deleted file mode 100755
index 131a2d46ceec85cc9d5f870ca32f381c70f797d9..0000000000000000000000000000000000000000
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/KeepAliveRedisPublisher.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bigbluebutton.client.endpoint.redis
-
-import scala.concurrent.duration._
-import scala.concurrent.ExecutionContext.Implicits.global
-import akka.actor.ActorSystem
-import org.bigbluebutton.client.SystemConfiguration
-//import org.bigbluebutton.common.messages.BbbAppsIsAliveMessage
-
-class KeepAliveRedisPublisher(val system: ActorSystem, sender: RedisPublisher) extends SystemConfiguration {
-
-  val startedOn = System.currentTimeMillis()
-
-  system.scheduler.schedule(2 seconds, 5 seconds) {
-//    val msg = new BbbAppsIsAliveMessage(startedOn, System.currentTimeMillis())
-//    sender.publish("bigbluebutton:from-bbb-apps:keepalive", msg.toJson())
-  }
-}
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/MessageSender.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/MessageSender.scala
deleted file mode 100755
index 191af624c8c0e67aa8be845784a1ca9942ed3255..0000000000000000000000000000000000000000
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/MessageSender.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bigbluebutton.client.endpoint.redis
-
-class MessageSender(publisher: RedisPublisher) {
-
-  def send(channel: String, data: String) {
-    publisher.publish(channel, data)
-  }
-}
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/Red5AppsRedisSubscriberActor.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/Red5AppsRedisSubscriberActor.scala
new file mode 100644
index 0000000000000000000000000000000000000000..0281a091f34ae86e23e4494eef8682934775e904
--- /dev/null
+++ b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/Red5AppsRedisSubscriberActor.scala
@@ -0,0 +1,50 @@
+package org.bigbluebutton.client.endpoint.redis
+
+import org.bigbluebutton.common2.redis.RedisSubscriberProvider
+import io.lettuce.core.pubsub.RedisPubSubListener
+import org.bigbluebutton.common2.bus.JsonMsgFromAkkaApps
+import org.bigbluebutton.common2.redis.RedisConfiguration
+import org.bigbluebutton.client.SystemConfiguration
+import akka.actor.ActorSystem
+import org.bigbluebutton.common2.redis.RedisSubscriber
+import org.bigbluebutton.common2.bus.JsonMsgFromAkkaAppsBus
+import akka.actor.Props
+import org.bigbluebutton.common2.bus.JsonMsgFromAkkaAppsEvent
+
+object Red5AppsRedisSubscriberActor extends RedisSubscriber with RedisConfiguration with SystemConfiguration {
+
+  val channels = Seq(fromAkkaAppsRedisChannel, fromAkkaAppsWbRedisChannel, fromAkkaAppsChatRedisChannel, fromAkkaAppsPresRedisChannel, fromThirdPartyRedisChannel)
+  val patterns = Seq("bigbluebutton:from-bbb-apps:*")
+
+  def props(system: ActorSystem, jsonMsgBus: JsonMsgFromAkkaAppsBus): Props =
+    Props(
+      classOf[Red5AppsRedisSubscriberActor],
+      system, jsonMsgBus,
+      redisHost, redisPort,
+      channels, patterns).withDispatcher("akka.redis-subscriber-worker-dispatcher")
+}
+
+class Red5AppsRedisSubscriberActor(system: ActorSystem, jsonMsgBus: JsonMsgFromAkkaAppsBus,
+                                   redisHost: String, redisPort: Int,
+                                   channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
+  extends RedisSubscriberProvider(system, "Red5AppsSub", channels, patterns, null) with SystemConfiguration {
+
+  override def addListener(appChannel: String) {
+    connection.addListener(new RedisPubSubListener[String, String] {
+      def message(channel: String, message: String): Unit = {
+        if (channels.contains(channel)) {
+          val receivedJsonMessage = new JsonMsgFromAkkaApps(channel, message)
+          jsonMsgBus.publish(JsonMsgFromAkkaAppsEvent(fromAkkaAppsJsonChannel, receivedJsonMessage))
+        }
+      }
+      def message(pattern: String, channel: String, message: String): Unit = { log.info("Subscribed to channel {} with pattern {}", channel, pattern) }
+      def psubscribed(pattern: String, count: Long): Unit = { log.info("Subscribed to pattern {}", pattern) }
+      def punsubscribed(pattern: String, count: Long): Unit = { log.info("Unsubscribed from pattern {}", pattern) }
+      def subscribed(channel: String, count: Long): Unit = { log.info("Subscribed to pattern {}", channel) }
+      def unsubscribed(channel: String, count: Long): Unit = { log.info("Unsubscribed from channel {}", channel) }
+    })
+  }
+
+  addListener(null)
+  subscribe()
+}
diff --git a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/RedisPublisher.scala b/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/RedisPublisher.scala
deleted file mode 100755
index 379b15f5dec53f025e454613d7c8b2a08bdcf042..0000000000000000000000000000000000000000
--- a/bbb-apps-common/src/main/scala/org/bigbluebutton/client/endpoint/redis/RedisPublisher.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bigbluebutton.client.endpoint.redis
-
-import redis.RedisClient
-import akka.actor.ActorSystem
-import akka.event.Logging
-import org.bigbluebutton.client.SystemConfiguration
-import akka.util.ByteString
-
-class RedisPublisher(val system: ActorSystem) extends SystemConfiguration {
-
-  val redis = RedisClient(redisHost, redisPort)(system)
-
-  val log = Logging(system, getClass)
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  redis.clientSetname("Red5AppsPub")
-
-  def publish(channel: String, data: String) {
-    //log.debug("PUBLISH TO [" + channel + "]: \n [" + data + "]")
-    redis.publish(channel, ByteString(data))
-  }
-
-}
diff --git a/bbb-common-message/build.sbt b/bbb-common-message/build.sbt
index 29cf68bec63494dc7c7a58eb54b78c7748c6a525..054aa4acd34f7ae83ac5ea420818bfcf71ade0fd 100755
--- a/bbb-common-message/build.sbt
+++ b/bbb-common-message/build.sbt
@@ -1,19 +1,23 @@
-name := "bbb-common-message"
-
-organization := "org.bigbluebutton"
-
-version := "0.0.19-SNAPSHOT"
-
-scalaVersion := "2.12.6"
-
-scalacOptions ++= Seq(
-  "-unchecked",
-  "-deprecation",
-  "-Xlint",
-  "-Ywarn-dead-code",
-  "-language:_",
-  "-target:jvm-1.8",
-  "-encoding", "UTF-8"
+import org.bigbluebutton.build._
+
+version := "0.0.20-SNAPSHOT"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
 )
 
 resolvers += Resolver.sonatypeRepo("releases")
@@ -26,32 +30,8 @@ retrieveManaged := true
 testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console", "junitxml")
 testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
 
-libraryDependencies ++= {
-  Seq(
-	  "com.google.code.gson"      %  "gson"              % "2.5"
-	)}
-
-// https://mvnrepository.com/artifact/org.scala-lang/scala-library
-libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value
-// https://mvnrepository.com/artifact/org.scala-lang/scala-compiler
-libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
-
-libraryDependencies += "junit" % "junit" % "4.12" % "test"
-libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
-
-// https://mvnrepository.com/artifact/org.scalactic/scalactic_2.12
-libraryDependencies += "org.scalactic" % "scalactic_2.12" % "3.0.3" % "test"
-
-// For generating test reports
-libraryDependencies += "org.pegdown" % "pegdown" % "1.6.0" % "test"
-
-// https://mvnrepository.com/artifact/org.scalatest/scalatest_2.12
-libraryDependencies += "org.scalatest" % "scalatest_2.12" % "3.0.3" % "test"
-
-// https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-scala_2.12
-libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala_2.12" % "2.9.6"
-
-seq(Revolver.settings: _*)
+Seq(Revolver.settings: _*)
+lazy val commonMessage = (project in file(".")).settings(name := "bbb-common-message", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
 //-----------
 // Packaging
@@ -71,12 +51,12 @@ seq(Revolver.settings: _*)
 // This forbids including Scala related libraries into the dependency
 //autoScalaLibrary := false
 
-/***************************
-* When developing, change the version above to x.x.x-SNAPSHOT then use the file resolver to
-* publish to the local maven repo using "sbt publish"
-*/
+/** *************************
+  * When developing, change the version above to x.x.x-SNAPSHOT then use the file resolver to
+  * publish to the local maven repo using "sbt publish"
+  */
 // Uncomment this to publish to local maven repo while commenting out the nexus repo
-publishTo := Some(Resolver.file("file",  new File(Path.userHome.absolutePath+"/.m2/repository")))
+publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath + "/.m2/repository")))
 
 
 // Comment this out when publishing to local maven repo using SNAPSHOT version.
@@ -101,15 +81,14 @@ pomExtra := (
     <url>git@github.com:bigbluebutton/bigbluebutton.git</url>
     <connection>scm:git:git@github.com:bigbluebutton/bigbluebutton.git</connection>
   </scm>
-  <developers>
-    <developer>
-      <id>ritzalam</id>
-      <name>Richard Alam</name>
-      <url>http://www.bigbluebutton.org</url>
-    </developer>
-  </developers>)
-  
+    <developers>
+      <developer>
+        <id>ritzalam</id>
+        <name>Richard Alam</name>
+        <url>http://www.bigbluebutton.org</url>
+      </developer>
+    </developers>)
+
 licenses := Seq("LGPL-3.0" -> url("http://opensource.org/licenses/LGPL-3.0"))
 
 homepage := Some(url("http://www.bigbluebutton.org"))
-  
diff --git a/bbb-common-message/deploy.sh b/bbb-common-message/deploy.sh
index ccba754eaaf8182e665e94d1210571e23ebfb7b4..f829bc13dc598da480ee4e512a87c9436925a359 100755
--- a/bbb-common-message/deploy.sh
+++ b/bbb-common-message/deploy.sh
@@ -1,2 +1 @@
-sbt clean
-sbt publish publishLocal
+sbt clean publish publishLocal
diff --git a/bbb-common-message/project/Build.scala b/bbb-common-message/project/Build.scala
deleted file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/bbb-common-message/project/Dependencies.scala b/bbb-common-message/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c8d886208a730623e74fade96419511c92e62676
--- /dev/null
+++ b/bbb-common-message/project/Dependencies.scala
@@ -0,0 +1,68 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+    val junit = "4.12"
+    val junitInterface = "0.11"
+    val scalactic = "3.0.3"
+
+    // Libraries
+    val akkaVersion = "2.5.17"
+    val gson = "2.8.5"
+    val jackson = "2.9.7"
+    val sl4j = "1.7.25"
+    val red5 = "1.0.10-M5"
+    val pool = "2.6.0"
+
+    // Redis
+    val lettuce = "5.1.3.RELEASE"
+
+    // Test
+    val scalaTest = "3.0.5"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaCompiler = "org.scala-lang" % "scala-compiler" % Versions.scala
+
+    val akkaActor = "com.typesafe.akka" % "akka-actor_2.12" % Versions.akkaVersion
+
+    val googleGson = "com.google.code.gson" % "gson" % Versions.gson
+    val jacksonModule = "com.fasterxml.jackson.module" %% "jackson-module-scala" % Versions.jackson
+    val sl4jApi = "org.slf4j" % "slf4j-api" % Versions.sl4j % "runtime"
+    val red5 = "org.red5" % "red5-server-common" % Versions.red5
+    val apachePool2 = "org.apache.commons" % "commons-pool2" % Versions.pool
+
+    val lettuceCore = "io.lettuce" % "lettuce-core" % Versions.lettuce
+  }
+
+  object Test {
+    val scalaTest = "org.scalatest" %% "scalatest" % Versions.scalaTest % "test"
+    val junit = "junit" % "junit" % Versions.junit % "test"
+    val junitInteface = "com.novocode" % "junit-interface" % Versions.junitInterface % "test"
+    val scalactic = "org.scalactic" % "scalactic_2.12" % Versions.scalactic % "test"
+  }
+
+  val testing = Seq(
+    Test.scalaTest,
+    Test.junit,
+    Test.junitInteface,
+    Test.scalactic)
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaCompiler,
+    Compile.akkaActor,
+    Compile.googleGson,
+    Compile.jacksonModule,
+    Compile.sl4jApi,
+    Compile.red5,
+    Compile.apachePool2,
+    Compile.lettuceCore) ++ testing
+}
diff --git a/bbb-common-message/project/build.properties b/bbb-common-message/project/build.properties
index a6e117b61042ee81c62ba3a0fc5210d9502944df..2e6e3d24608ee15e892ed3b16d84224f7667e808 100755
--- a/bbb-common-message/project/build.properties
+++ b/bbb-common-message/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=1.2.6
\ No newline at end of file
diff --git a/bbb-common-message/project/plugins.sbt b/bbb-common-message/project/plugins.sbt
index 5ab7b095f69a2b3d8a3bf5350fa7e7e1a64f8f2f..3559bf68d62ef19f25fa810533bbe596eb022d02 100755
--- a/bbb-common-message/project/plugins.sbt
+++ b/bbb-common-message/project/plugins.sbt
@@ -2,8 +2,8 @@ addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
+addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1")
 
-addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
+addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.8")
 
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/EventRecordingService.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/Keys.java
old mode 100755
new mode 100644
similarity index 50%
rename from bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/EventRecordingService.java
rename to bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/Keys.java
index d534387e2e99c3a2a0c0b38bdb7511a69bf0a0d3..96509383d5f8e564b9f480baa862bc2277a6b0c0
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/EventRecordingService.java
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/Keys.java
@@ -1,7 +1,7 @@
 /**
 * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
 * 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
 *
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
@@ -16,28 +16,13 @@
 * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 *
 */
-package org.bigbluebutton.app.screenshare;
 
+package org.bigbluebutton.common2.redis;
 
-import java.util.Map;
-
-import redis.clients.jedis.Jedis;
-
-public class EventRecordingService {
-	private static final String COLON = ":";
-	
-	private final String  host;
-	private final int port;
-	
-	public EventRecordingService(String host, int port) {
-		this.host = host;
-		this.port = port;
-	}
-	
-	public void record(String meetingId, Map<String, String> event) {		
-		Jedis jedis = new Jedis(host, port);
-		Long msgid = jedis.incr("global:nextRecordedMsgId");
-		jedis.hmset("recording:" + meetingId + COLON + msgid, event);
-		jedis.rpush("meeting:" + meetingId + COLON + "recordings", msgid.toString());						
-	}
+public final class Keys {
+    public static final String MEETING = "meeting-";
+    public static final String MEETINGS = "meetings";
+    public static final String MEETING_INFO = "meeting:info:";
+    public static final String BREAKOUT_MEETING = "meeting:breakout:";
+    public static final String BREAKOUT_ROOMS = "meeting:breakout:rooms:";
 }
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/RedisAwareCommunicator.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/RedisAwareCommunicator.java
new file mode 100644
index 0000000000000000000000000000000000000000..23dc26d26f04721273a3a8f552001d87dfd0ed8a
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/RedisAwareCommunicator.java
@@ -0,0 +1,98 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+package org.bigbluebutton.common2.redis;
+
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.slf4j.Logger;
+
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.event.Event;
+import io.lettuce.core.event.EventBus;
+import io.lettuce.core.event.connection.ConnectedEvent;
+import io.lettuce.core.event.connection.ConnectionActivatedEvent;
+import io.lettuce.core.event.connection.ConnectionDeactivatedEvent;
+import io.lettuce.core.event.connection.DisconnectedEvent;
+import reactor.core.Disposable;
+
+public abstract class RedisAwareCommunicator {
+
+    protected RedisClient redisClient;
+
+    protected Disposable eventBusSubscription;
+
+    protected EventBus eventBus;
+
+    protected String host;
+    protected String password;
+    protected int port;
+    protected String clientName;
+    protected int expireKey;
+
+    public abstract void start();
+
+    public abstract void stop();
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    protected void connectionStatusHandler(Event event, Logger log) {
+        if (event instanceof ConnectedEvent) {
+            log.info("Connected to redis");
+        } else if (event instanceof ConnectionActivatedEvent) {
+            log.info("Connected to redis activated");
+        } else if (event instanceof DisconnectedEvent) {
+            log.info("Disconnected from redis");
+        } else if (event instanceof ConnectionDeactivatedEvent) {
+            log.info("Connected to redis deactivated");
+        }
+    }
+
+    public void setClientName(String clientName) {
+        this.clientName = clientName;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public void setExpireKey(int expireKey) {
+        this.expireKey = expireKey;
+    }
+
+    protected GenericObjectPoolConfig createPoolingConfig() {
+        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
+        config.setMaxTotal(32);
+        config.setMaxIdle(8);
+        config.setMinIdle(1);
+        config.setTestOnBorrow(true);
+        config.setTestOnReturn(true);
+        config.setTestWhileIdle(true);
+        config.setNumTestsPerEvictionRun(12);
+        config.setMaxWaitMillis(5000);
+        config.setTimeBetweenEvictionRunsMillis(60000);
+        config.setBlockWhenExhausted(true);
+        return config;
+    }
+}
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/RedisStorageService.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/RedisStorageService.java
new file mode 100644
index 0000000000000000000000000000000000000000..19f844bc159ef7979c4dbcf1b9f546d2067adb0e
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/RedisStorageService.java
@@ -0,0 +1,116 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+package org.bigbluebutton.common2.redis;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.lettuce.core.ClientOptions;
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.RedisURI;
+import io.lettuce.core.api.StatefulRedisConnection;
+import io.lettuce.core.api.sync.RedisCommands;
+
+public class RedisStorageService extends RedisAwareCommunicator {
+
+    private static Logger log = LoggerFactory.getLogger(RedisStorageService.class);
+
+    StatefulRedisConnection<String, String> connection;
+
+    public void start() {
+        log.info("Starting RedisStorageService with client name: {}", clientName);
+        RedisURI redisUri = RedisURI.Builder.redis(this.host, this.port).withClientName(this.clientName)
+                .withPassword(this.password).build();
+
+        redisClient = RedisClient.create(redisUri);
+        redisClient.setOptions(ClientOptions.builder().autoReconnect(true).build());
+        eventBus = redisClient.getResources().eventBus();
+        eventBusSubscription = eventBus.get().subscribe(e -> connectionStatusHandler(e, log));
+
+        connection = redisClient.connect();
+    }
+
+    public void stop() {
+        eventBusSubscription.dispose();
+        connection.close();
+        redisClient.shutdown();
+        log.info("RedisStorageService Stopped");
+    }
+
+    public void recordMeetingInfo(String meetingId, Map<String, String> info) {
+        log.debug("Storing meeting {} metadata {}", meetingId, info);
+        recordMeeting(Keys.MEETING_INFO + meetingId, info);
+    }
+
+    public void recordBreakoutInfo(String meetingId, Map<String, String> breakoutInfo) {
+        log.debug("Saving breakout metadata in {}", meetingId);
+        recordMeeting(Keys.BREAKOUT_MEETING + meetingId, breakoutInfo);
+    }
+
+    public void addBreakoutRoom(String parentId, String breakoutId) {
+        log.debug("Saving breakout room for meeting {}", parentId);
+        RedisCommands<String, String> commands = connection.sync();
+        commands.sadd(Keys.BREAKOUT_ROOMS + parentId, breakoutId);
+    }
+
+    public void record(String meetingId, Map<String, String> event) {
+        log.debug("Recording meeting event {} inside a transaction", meetingId);
+        RedisCommands<String, String> commands = connection.sync();
+        Long msgid = commands.incr("global:nextRecordedMsgId");
+        commands.hmset("recording:" + meetingId + ":" + msgid, event);
+        commands.rpush("meeting:" + meetingId + ":" + "recordings", Long.toString(msgid));
+    }
+
+    // @fixme: not used anywhere
+    public void removeMeeting(String meetingId) {
+        log.debug("Removing meeting meeting {} inside a transaction", meetingId);
+        RedisCommands<String, String> commands = connection.sync();
+        commands.del(Keys.MEETING + meetingId);
+        commands.srem(Keys.MEETINGS + meetingId);
+    }
+
+    public void recordAndExpire(String meetingId, Map<String, String> event) {
+        log.debug("Recording meeting event {} inside a transaction", meetingId);
+        RedisCommands<String, String> commands = connection.sync();
+
+        Long msgid = commands.incr("global:nextRecordedMsgId");
+        String key = "recording:" + meetingId + ":" + msgid;
+        commands.hmset(key, event);
+        /**
+         * We set the key to expire after 14 days as we are still recording the
+         * event into redis even if the meeting is not recorded. (ralam sept 23,
+         * 2015)
+         */
+        commands.expire(key, expireKey);
+        key = "meeting:" + meetingId + ":recordings";
+        commands.rpush(key, Long.toString(msgid));
+        commands.expire(key, expireKey);
+    }
+
+    private String recordMeeting(String key, Map<String, String> info) {
+        log.debug("Storing metadata {}", info);
+        String result = "";
+        RedisCommands<String, String> commands = connection.sync();
+        result = commands.hmset(key, info);
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageDistributor.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageDistributor.java
similarity index 89%
rename from bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageDistributor.java
rename to bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageDistributor.java
index b51ed206c8f6ea6b5da5e3681709dbfe103f6f3b..89c8e9e46587090caa945a3a28fd8cb8529add65 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageDistributor.java
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageDistributor.java
@@ -1,4 +1,4 @@
-package org.bigbluebutton.red5.pubsub;
+package org.bigbluebutton.common2.redis.pubsub;
 
 import java.util.Set;
 
@@ -22,4 +22,4 @@ public class MessageDistributor {
             listener.handleMessage(pattern, channel, message);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageHandler.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageHandler.java
similarity index 85%
rename from bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageHandler.java
rename to bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageHandler.java
index b94db88559d8e7d351690cd88b72ad4ba228099a..95bbde9e690becf55776d73e61a8ddd548e32365 100755
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageHandler.java
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageHandler.java
@@ -16,8 +16,8 @@
 * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 *
 */
-package org.bigbluebutton.voiceconf.messaging;
+package org.bigbluebutton.common2.redis.pubsub;
 
 public interface MessageHandler {
-	void handleMessage(String pattern, String channel, String message);
+    void handleMessage(String pattern, String channel, String message);
 }
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageReceiver.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageReceiver.java
new file mode 100755
index 0000000000000000000000000000000000000000..ade4b5d648f11a4da9ba29adbb72de43d921edce
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageReceiver.java
@@ -0,0 +1,121 @@
+package org.bigbluebutton.common2.redis.pubsub;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.bigbluebutton.common2.redis.RedisAwareCommunicator;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+import io.lettuce.core.ClientOptions;
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.RedisFuture;
+import io.lettuce.core.RedisURI;
+import io.lettuce.core.pubsub.RedisPubSubListener;
+import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
+import io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands;
+import io.lettuce.core.support.ConnectionPoolSupport;
+
+public class MessageReceiver extends RedisAwareCommunicator {
+    private static Logger log = Red5LoggerFactory.getLogger(MessageReceiver.class, "video");
+
+    private ReceivedMessageHandler handler;
+
+    GenericObjectPool<StatefulRedisPubSubConnection<String, String>> connectionPool;
+
+    private final Executor runExec = Executors.newSingleThreadExecutor();
+
+    private volatile boolean receiveMessage = false;
+
+    private final String FROM_BBB_APPS_PATTERN = "from-akka-apps-redis-channel";
+
+    public void start() {
+        log.info("Ready to receive messages from Redis pubsub.");
+        receiveMessage = true;
+
+        RedisURI redisUri = RedisURI.Builder.redis(this.host, this.port).withClientName(this.clientName).build();
+        if (!this.password.isEmpty()) {
+            redisUri.setPassword(this.password);
+        }
+
+        redisClient = RedisClient.create(redisUri);
+        redisClient.setOptions(ClientOptions.builder().autoReconnect(true).build());
+        eventBus = redisClient.getResources().eventBus();
+        eventBusSubscription = eventBus.get().subscribe(e -> connectionStatusHandler(e, log));
+
+        connectionPool = ConnectionPoolSupport.createGenericObjectPool(() -> redisClient.connectPubSub(),
+                createPoolingConfig());
+
+        Runnable messageReceiver = new Runnable() {
+            public void run() {
+                if (receiveMessage) {
+                    try (StatefulRedisPubSubConnection<String, String> connection = connectionPool.borrowObject()) {
+                        if (receiveMessage) {
+                            connection.addListener(new MessageListener());
+
+                            RedisPubSubAsyncCommands<String, String> async = connection.async();
+                            RedisFuture<Void> future = async.subscribe(FROM_BBB_APPS_PATTERN);
+                        }
+                    } catch (Exception e) {
+                        log.error("Error resubscribing to channels: ", e);
+                    }
+                }
+            }
+        };
+
+        runExec.execute(messageReceiver);
+    }
+
+    public void stop() {
+        receiveMessage = false;
+        connectionPool.close();
+        redisClient.shutdown();
+        log.info("MessageReceiver Stopped");
+    }
+
+    public void setMessageHandler(ReceivedMessageHandler handler) {
+        this.handler = handler;
+    }
+
+    private class MessageListener implements RedisPubSubListener<String, String> {
+
+        @Override
+        public void message(String channel, String message) {
+            handler.handleMessage("", channel, message);
+        }
+
+        @Override
+        public void message(String pattern, String channel, String message) {
+            log.debug("RECEIVED onPMessage" + channel + " message=\n" + message);
+            Runnable task = new Runnable() {
+                public void run() {
+                    handler.handleMessage(pattern, channel, message);
+                }
+            };
+
+            runExec.execute(task);
+        }
+
+        @Override
+        public void subscribed(String channel, long count) {
+            log.debug("Subscribed to the channel: " + channel);
+        }
+
+        @Override
+        public void psubscribed(String pattern, long count) {
+            log.debug("Subscribed to the pattern: " + pattern);
+        }
+
+        @Override
+        public void unsubscribed(String channel, long count) {
+            log.debug("Unsubscribed from the channel: " + channel);
+        }
+
+        @Override
+        public void punsubscribed(String pattern, long count) {
+            log.debug("Unsubscribed from the pattern: " + pattern);
+        }
+    }
+
+}
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageSender.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageSender.java
new file mode 100755
index 0000000000000000000000000000000000000000..8209f5bf76934d9959a385861ef773f184845bd4
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageSender.java
@@ -0,0 +1,94 @@
+package org.bigbluebutton.common2.redis.pubsub;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.bigbluebutton.common2.redis.RedisAwareCommunicator;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+import io.lettuce.core.ClientOptions;
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.RedisFuture;
+import io.lettuce.core.RedisURI;
+import io.lettuce.core.api.async.RedisAsyncCommands;
+import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
+import io.lettuce.core.support.ConnectionPoolSupport;
+
+public class MessageSender extends RedisAwareCommunicator {
+    private static Logger log = Red5LoggerFactory.getLogger(MessageSender.class, "bigbluebutton");
+
+    GenericObjectPool<StatefulRedisPubSubConnection<String, String>> connectionPool;
+
+    private volatile boolean sendMessage = false;
+
+    private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
+    private final Executor runExec = Executors.newSingleThreadExecutor();
+    private BlockingQueue<MessageToSend> messages = new LinkedBlockingQueue<MessageToSend>();
+
+    public void stop() {
+        sendMessage = false;
+        connectionPool.close();
+        redisClient.shutdown();
+    }
+
+    public void start() {
+        RedisURI redisUri = RedisURI.Builder.redis(this.host, this.port).withClientName(this.clientName).build();
+        if (!this.password.isEmpty()) {
+            redisUri.setPassword(this.password);
+        }
+
+        redisClient = RedisClient.create(redisUri);
+        redisClient.setOptions(ClientOptions.builder().autoReconnect(true).build());
+        eventBus = redisClient.getResources().eventBus();
+        eventBusSubscription = eventBus.get().subscribe(e -> connectionStatusHandler(e, log));
+
+        connectionPool = ConnectionPoolSupport.createGenericObjectPool(() -> redisClient.connectPubSub(),
+                createPoolingConfig());
+
+        log.info("Redis org.bigbluebutton.red5.pubsub.message publisher starting!");
+        try {
+            sendMessage = true;
+
+            Runnable messageSender = new Runnable() {
+                public void run() {
+                    while (sendMessage) {
+                        try {
+                            MessageToSend msg = messages.take();
+                            publish(msg.getChannel(), msg.getMessage());
+                        } catch (InterruptedException e) {
+                            log.warn("Failed to get org.bigbluebutton.common2.redis.pubsub from queue.");
+                        }
+                    }
+                }
+            };
+            msgSenderExec.execute(messageSender);
+        } catch (Exception e) {
+            log.error("Error subscribing to channels: " + e.getMessage());
+        }
+
+    }
+
+    public void send(String channel, String message) {
+        MessageToSend msg = new MessageToSend(channel, message);
+        messages.add(msg);
+    }
+
+    private void publish(final String channel, final String message) {
+        Runnable task = new Runnable() {
+            public void run() {
+                try (StatefulRedisPubSubConnection<String, String> connection = connectionPool.borrowObject()) {
+                    RedisAsyncCommands<String, String> async = connection.async();
+                    RedisFuture<Long> future = async.publish(channel, message);
+                } catch (Exception e) {
+                    log.warn("Cannot publish the org.bigbluebutton.red5.pubsub.message to redis", e);
+                }
+            }
+        };
+
+        runExec.execute(task);
+    }
+}
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageToSend.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageToSend.java
new file mode 100755
index 0000000000000000000000000000000000000000..dba49444b87ae7ac2d2e9040ff7d44a6ffd81bd9
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/MessageToSend.java
@@ -0,0 +1,19 @@
+package org.bigbluebutton.common2.redis.pubsub;
+
+public class MessageToSend {
+    private final String channel;
+    private final String message;
+
+    public MessageToSend(String channel, String message) {
+        this.channel = channel;
+        this.message = message;
+    }
+
+    public String getChannel() {
+        return channel;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+}
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/ReceivedMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/ReceivedMessage.java
similarity index 87%
rename from bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/ReceivedMessage.java
rename to bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/ReceivedMessage.java
index 41c775f739fc95f8e0c827ff1aa4a2adf6976ee5..01f893f309ef0ae497cdcc54a6808e0f252c72a2 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/ReceivedMessage.java
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/ReceivedMessage.java
@@ -1,4 +1,4 @@
-package org.bigbluebutton.red5.pubsub;
+package org.bigbluebutton.common2.redis.pubsub;
 
 public class ReceivedMessage {
     private final String pattern;
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/ReceivedMessageHandler.java b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/ReceivedMessageHandler.java
similarity index 90%
rename from bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/ReceivedMessageHandler.java
rename to bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/ReceivedMessageHandler.java
index ddafee0b6e8b2897c8da27a344c24e7ad63cd8fe..ed296626114b185eaf805ef21a73e665416778f3 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/ReceivedMessageHandler.java
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common2/redis/pubsub/ReceivedMessageHandler.java
@@ -1,15 +1,16 @@
-package org.bigbluebutton.red5.pubsub;
+package org.bigbluebutton.common2.redis.pubsub;
 
-
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.LinkedBlockingQueue;
 
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
 public class ReceivedMessageHandler {
-    private static Logger log = Red5LoggerFactory.getLogger(ReceivedMessageHandler.class, "video");
+    private static Logger log = Red5LoggerFactory
+            .getLogger(ReceivedMessageHandler.class/* , "video" */);
 
     private BlockingQueue<ReceivedMessage> receivedMessages = new LinkedBlockingQueue<ReceivedMessage>();
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/bus/IncomingJsonMessageBus.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/IncomingJsonMessageBus.scala
old mode 100755
new mode 100644
similarity index 94%
rename from akka-bbb-apps/src/main/scala/org/bigbluebutton/core/bus/IncomingJsonMessageBus.scala
rename to bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/IncomingJsonMessageBus.scala
index f2e9aa281de9441af7bf0fe3fe1c7e63f91fa59d..96dbff59b4312665dcd909d73d3e3a3d1b102731
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/bus/IncomingJsonMessageBus.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/IncomingJsonMessageBus.scala
@@ -1,4 +1,4 @@
-package org.bigbluebutton.core.bus
+package org.bigbluebutton.common2.bus
 
 import akka.actor.ActorRef
 import akka.event.{ EventBus, LookupClassification }
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/JsonMsgFromAkkaAppsBus.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/JsonMsgFromAkkaAppsBus.scala
old mode 100755
new mode 100644
similarity index 88%
rename from bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/JsonMsgFromAkkaAppsBus.scala
rename to bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/JsonMsgFromAkkaAppsBus.scala
index 5d26e2c23bb7a1c4f27a150d64a8a1fe4f4a0907..871f6f76f9948b4fc7b7fd0abbdf3cbb9bdd6c6b
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/JsonMsgFromAkkaAppsBus.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/JsonMsgFromAkkaAppsBus.scala
@@ -1,7 +1,7 @@
-package org.bigbluebutton.api2.bus
+package org.bigbluebutton.common2.bus
 
 import akka.actor.ActorRef
-import akka.event.{EventBus, LookupClassification}
+import akka.event.{ EventBus, LookupClassification }
 
 case class JsonMsgFromAkkaApps(name: String, data: String)
 case class JsonMsgFromAkkaAppsEvent(val topic: String, val payload: JsonMsgFromAkkaApps)
@@ -23,7 +23,7 @@ class JsonMsgFromAkkaAppsBus extends EventBus with LookupClassification {
   // must define a full order over the subscribers, expressed as expected from
   // `java.lang.Comparable.compare`
   override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
-  a.compareTo(b)
+    a.compareTo(b)
 
   // determines the initial size of the index data structure
   // used internally (i.e. the expected number of different classifiers)
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MsgFromAkkaAppsEventBus.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/MsgFromAkkaAppsEventBus.scala
old mode 100755
new mode 100644
similarity index 91%
rename from bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MsgFromAkkaAppsEventBus.scala
rename to bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/MsgFromAkkaAppsEventBus.scala
index e9f25b91a5f9e2f8f224bed7e482334204ea806a..097df4a29c433f8e7b8e3dc1702696f1b8a2ad12
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MsgFromAkkaAppsEventBus.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/MsgFromAkkaAppsEventBus.scala
@@ -2,9 +2,9 @@ package org.bigbluebutton.api2.bus
 
 import akka.actor.ActorRef
 import akka.event.{EventBus, LookupClassification}
-import org.bigbluebutton.common2.msgs.{BbbCommonEnvCoreMsg}
+import org.bigbluebutton.common2.msgs.BbbCommonMsg
 
-case class MsgFromAkkaApps(val topic: String, val payload: BbbCommonEnvCoreMsg)
+case class MsgFromAkkaApps(val topic: String, val payload: BbbCommonMsg)
 
 class MsgFromAkkaAppsEventBus extends EventBus with LookupClassification {
   type Event = MsgFromAkkaApps
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageEventBus.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/OldMessageEventBus.scala
similarity index 86%
rename from bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageEventBus.scala
rename to bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/OldMessageEventBus.scala
index cccd288cdcbf317ad7ea7da62761dcbdfcb4e9f6..9b7c6bdd0b248a80efe49dc062501f0d472338dc 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageEventBus.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/bus/OldMessageEventBus.scala
@@ -1,7 +1,8 @@
-package org.bigbluebutton.api2.bus
+package org.bigbluebutton.common2.bus
 
 import akka.actor.ActorRef
 import akka.event.{EventBus, LookupClassification}
+import akka.actor.actorRef2Scala
 
 case class OldReceivedJsonMessage(pattern: String, channel: String, msg: String)
 case class OldIncomingJsonMessage(val topic: String, val payload: OldReceivedJsonMessage)
@@ -11,7 +12,7 @@ class OldMessageEventBus extends EventBus with LookupClassification {
   type Classifier = String
   type Subscriber = ActorRef
 
-  // is used for extracting the classifier from the incoming events
+  // is used for extracting te classifier from the incoming events
   override protected def classify(event: Event): Classifier = event.topic
 
   // will be invoked for each event for all subscribers which registered themselves
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/MessageSender.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/MessageSender.scala
similarity index 71%
rename from bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/MessageSender.scala
rename to bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/MessageSender.scala
index be38ef420165f015adbeb0a6675f4f213dacd304..2426a353e6d687ebfe073acc28337f48b961444a 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/MessageSender.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/MessageSender.scala
@@ -1,4 +1,4 @@
-package org.bigbluebutton.api2.endpoint.redis
+package org.bigbluebutton.common2.redis
 
 class MessageSender(publisher: RedisPublisher) {
 
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisClientProvider.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisClientProvider.scala
new file mode 100644
index 0000000000000000000000000000000000000000..afeba57bf44c5604908cbc22711342ee580fa1a0
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisClientProvider.scala
@@ -0,0 +1,15 @@
+package org.bigbluebutton.common2.redis
+
+import akka.actor.ActorSystem
+import io.lettuce.core.ClientOptions
+import io.lettuce.core.RedisClient
+import io.lettuce.core.RedisURI
+
+abstract class RedisClientProvider(val system: ActorSystem, val clientName: String) extends RedisConfiguration {
+  // Set the name of this client to be able to distinguish when doing
+  // CLIENT LIST on redis-cli
+  val redisUri = RedisURI.Builder.redis(redisHost, redisPort).withClientName(clientName).withPassword(redisPassword).build()
+
+  var redis = RedisClient.create(redisUri)
+  redis.setOptions(ClientOptions.builder().autoReconnect(true).build())
+}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisConfiguration.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisConfiguration.scala
new file mode 100644
index 0000000000000000000000000000000000000000..8dcfd16ff578dc24aa0049318a72e050b8344881
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisConfiguration.scala
@@ -0,0 +1,25 @@
+package org.bigbluebutton.common2.redis
+
+import scala.util.Try
+import com.typesafe.config.ConfigFactory
+
+trait RedisConfiguration {
+  val config = ConfigFactory.load()
+
+  // Redis server configuration
+  lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
+  lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
+  lazy val redisPassword = Try(config.getString("redis.password")).getOrElse("")
+  lazy val redisExpireKey = Try(config.getInt("redis.keyExpiry")).getOrElse(1209600)
+
+  // Redis channels
+  lazy val toAkkaAppsRedisChannel = Try(config.getString("redis.toAkkaAppsRedisChannel")).getOrElse("to-akka-apps-redis-channel")
+  lazy val fromAkkaAppsRedisChannel = Try(config.getString("redis.fromAkkaAppsRedisChannel")).getOrElse("from-akka-apps-redis-channel")
+
+  lazy val toVoiceConfRedisChannel = Try(config.getString("redis.toVoiceConfRedisChannel")).getOrElse("to-voice-conf-redis-channel")
+  lazy val fromVoiceConfRedisChannel = Try(config.getString("redis.fromVoiceConfRedisChannel")).getOrElse("from-voice-conf-redis-channel")
+
+  lazy val fromAkkaAppsWbRedisChannel = Try(config.getString("redis.fromAkkaAppsWbRedisChannel")).getOrElse("from-akka-apps-wb-redis-channel")
+  lazy val fromAkkaAppsChatRedisChannel = Try(config.getString("redis.fromAkkaAppsChatRedisChannel")).getOrElse("from-akka-apps-chat-redis-channel")
+  lazy val fromAkkaAppsPresRedisChannel = Try(config.getString("redis.fromAkkaAppsPresRedisChannel")).getOrElse("from-akka-apps-pres-redis-channel")
+}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisConnectionHandler.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisConnectionHandler.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c30003c95da1becaaff67d45c705d67bcf09a650
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisConnectionHandler.scala
@@ -0,0 +1,29 @@
+package org.bigbluebutton.common2.redis
+
+import io.lettuce.core.RedisClient
+import io.lettuce.core.event.Event
+import io.lettuce.core.event.EventBus
+import io.lettuce.core.event.connection.{ ConnectionDeactivatedEvent, ConnectionActivatedEvent, ConnectedEvent, DisconnectedEvent }
+import reactor.core.Disposable
+import akka.event.LoggingAdapter
+
+trait RedisConnectionHandler {
+
+  def subscribeToEventBus(redis: RedisClient, log: LoggingAdapter) {
+    val eventBus: EventBus = redis.getResources().eventBus();
+    // @todo : unsubscribe when connection is closed
+    val eventBusSubscription: Disposable = eventBus.get().subscribe(e => connectionStatusHandler(e, log))
+  }
+
+  def connectionStatusHandler(event: Event, log: LoggingAdapter) {
+    if (event.isInstanceOf[ConnectedEvent]) {
+      log.info("Connected to redis");
+    } else if (event.isInstanceOf[ConnectionActivatedEvent]) {
+      log.info("Connection to redis activated");
+    } else if (event.isInstanceOf[DisconnectedEvent]) {
+      log.info("Disconnected from redis");
+    } else if (event.isInstanceOf[ConnectionDeactivatedEvent]) {
+      log.info("Connection to redis deactivated");
+    }
+  }
+}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisPublisher.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisPublisher.scala
new file mode 100755
index 0000000000000000000000000000000000000000..47c5af6f10dcba75a018bcc1658bfebd12219fb2
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisPublisher.scala
@@ -0,0 +1,21 @@
+package org.bigbluebutton.common2.redis
+
+import akka.actor.ActorSystem
+import akka.event.Logging
+
+class RedisPublisher(system: ActorSystem, clientName: String) extends RedisClientProvider(system, clientName) with RedisConnectionHandler {
+
+  val log = Logging(system, getClass)
+
+  subscribeToEventBus(redis, log)
+
+  val connection = redis.connectPubSub()
+
+  redis.connect()
+
+  def publish(channel: String, data: String) {
+    val async = connection.async();
+    async.publish(channel, data);
+  }
+
+}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisStorageProvider.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisStorageProvider.scala
new file mode 100644
index 0000000000000000000000000000000000000000..71fc9df41a4c2d2f755c794a949d42db41b46203
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisStorageProvider.scala
@@ -0,0 +1,13 @@
+package org.bigbluebutton.common2.redis
+
+import akka.actor.ActorSystem
+
+abstract class RedisStorageProvider(system: ActorSystem, clientName: String) extends RedisConfiguration {
+  var redis = new RedisStorageService()
+  redis.setHost(redisHost)
+  redis.setPort(redisPort)
+  redis.setPassword(redisPassword)
+  redis.setExpireKey(redisExpireKey)
+  redis.setClientName(clientName)
+  redis.start();
+}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisSubscriber.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisSubscriber.scala
new file mode 100644
index 0000000000000000000000000000000000000000..5c65a338577604ac1c9b342740bc99f7641b8591
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisSubscriber.scala
@@ -0,0 +1,6 @@
+package org.bigbluebutton.common2.redis
+
+trait RedisSubscriber extends RedisConfiguration {
+  val channels: Seq[String]
+  val patterns: Seq[String]
+}
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisSubscriberProvider.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisSubscriberProvider.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e091e9ad25919454973ae8f4bf450c712d89eccc
--- /dev/null
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/redis/RedisSubscriberProvider.scala
@@ -0,0 +1,62 @@
+package org.bigbluebutton.common2.redis
+
+import akka.actor.ActorSystem
+import org.bigbluebutton.common2.bus.ReceivedJsonMessage
+import org.bigbluebutton.common2.bus.IncomingJsonMessage
+import io.lettuce.core.pubsub.RedisPubSubListener
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
+import akka.actor.ActorLogging
+import akka.actor.Actor
+
+import akka.actor.ActorSystem
+import akka.actor.OneForOneStrategy
+import akka.actor.SupervisorStrategy.Resume
+import java.io.StringWriter
+import scala.concurrent.duration._
+import java.io.PrintWriter
+
+abstract class RedisSubscriberProvider(system: ActorSystem, clientName: String,
+                                       channels: Seq[String], patterns: Seq[String],
+                                       jsonMsgBus: IncomingJsonMessageBus)
+  extends RedisClientProvider(system, clientName) with RedisConnectionHandler with Actor with ActorLogging {
+
+  subscribeToEventBus(redis, log)
+
+  var connection = redis.connectPubSub()
+
+  def addListener(appChannel: String) {
+    connection.addListener(new RedisPubSubListener[String, String] {
+      def message(channel: String, message: String): Unit = {
+        if (channels.contains(channel)) {
+          val receivedJsonMessage = new ReceivedJsonMessage(channel, message)
+          jsonMsgBus.publish(IncomingJsonMessage(appChannel, receivedJsonMessage))
+        }
+      }
+      def message(pattern: String, channel: String, message: String): Unit = { log.info("Subscribed to channel {} with pattern {}", channel, pattern) }
+      def psubscribed(pattern: String, count: Long): Unit = { log.info("Subscribed to pattern {}", pattern) }
+      def punsubscribed(pattern: String, count: Long): Unit = { log.info("Unsubscribed from pattern {}", pattern) }
+      def subscribed(channel: String, count: Long): Unit = { log.info("Subscribed to pattern {}", channel) }
+      def unsubscribed(channel: String, count: Long): Unit = { log.info("Unsubscribed from channel {}", channel) }
+    })
+  }
+
+  def subscribe() {
+    val async = connection.async()
+    for (channel <- channels) async.subscribe(channel)
+    for (pattern <- patterns) async.psubscribe(pattern)
+  }
+
+  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
+    case e: Exception => {
+      val sw: StringWriter = new StringWriter()
+      sw.write("An exception has been thrown on " + getClass + ", exception message [" + e.getMessage + "] (full stacktrace below)\n")
+      e.printStackTrace(new PrintWriter(sw))
+      log.error(sw.toString())
+      Resume
+    }
+  }
+
+  def receive = {
+    case _ => // do nothing
+  }
+}
diff --git a/bbb-common-message/src/test/scala/org/bigbluebutton/common2/TestFixtures.scala b/bbb-common-message/src/test/scala/org/bigbluebutton/common2/TestFixtures.scala
index d2a42e7dffe3c62f49da15b23c8f54b205409559..ccfa4e929a14eaa1bd2f6100e3872be1433271a8 100755
--- a/bbb-common-message/src/test/scala/org/bigbluebutton/common2/TestFixtures.scala
+++ b/bbb-common-message/src/test/scala/org/bigbluebutton/common2/TestFixtures.scala
@@ -2,7 +2,6 @@ package org.bigbluebutton.common2
 
 import org.bigbluebutton.common2.domain._
 
-
 trait TestFixtures {
   val meetingId = "testMeetingId"
   val externalMeetingId = "testExternalMeetingId"
@@ -12,6 +11,15 @@ trait TestFixtures {
   val record = false
   val voiceConfId = "85115"
   val durationInMinutes = 10
+
+  val maxInactivityTimeoutMinutes = 120
+  val warnMinutesBeforeMax = 30
+  val meetingExpireIfNoUserJoinedInMinutes = 5
+  val meetingExpireWhenLastUserLeftInMinutes = 10
+  val userInactivityInspectTimerInMinutes = 60
+  val userInactivityThresholdInMinutes = 10
+  val userActivitySignResponseDelayInMinutes = 5
+
   val autoStartRecording = false
   val allowStartStopRecording = false
   val webcamsOnlyForModerator = false
@@ -25,19 +33,23 @@ trait TestFixtures {
   val modOnlyMessage = "Moderator only message"
   val dialNumber = "613-555-1234"
   val maxUsers = 25
+  val muteOnStart = false
   val guestPolicy = "ALWAYS_ASK"
   val metadata: collection.immutable.Map[String, String] = Map("foo" -> "bar", "bar" -> "baz", "baz" -> "foo")
 
   val meetingProp = MeetingProp(name = meetingName, extId = externalMeetingId, intId = meetingId,
     isBreakout = isBreakout.booleanValue())
-  val breakoutProps = BreakoutProps(parentId = parentMeetingId, sequence = sequence, breakoutRooms = Vector())
-  val durationProps = DurationProps(duration = durationInMinutes, createdTime = createTime, createdDate = createDate)
+  val breakoutProps = BreakoutProps(parentId = parentMeetingId, sequence = sequence, freeJoin = false, breakoutRooms = Vector())
+
+  val durationProps = DurationProps(duration = durationInMinutes, createdTime = createTime, createdDate = createDate, maxInactivityTimeoutMinutes = maxInactivityTimeoutMinutes, warnMinutesBeforeMax = warnMinutesBeforeMax,
+    meetingExpireIfNoUserJoinedInMinutes = meetingExpireIfNoUserJoinedInMinutes, meetingExpireWhenLastUserLeftInMinutes = meetingExpireWhenLastUserLeftInMinutes,
+    userInactivityInspectTimerInMinutes = userInactivityInspectTimerInMinutes, userInactivityThresholdInMinutes = userInactivityInspectTimerInMinutes, userActivitySignResponseDelayInMinutes = userActivitySignResponseDelayInMinutes)
   val password = PasswordProp(moderatorPass = moderatorPassword, viewerPass = viewerPassword)
   val recordProp = RecordProp(record = record, autoStartRecording = autoStartRecording,
     allowStartStopRecording = allowStartStopRecording)
   val welcomeProp = WelcomeProp(welcomeMsgTemplate = welcomeMsgTemplate, welcomeMsg = welcomeMsg,
     modOnlyMessage = modOnlyMessage)
-  val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber)
+  val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart)
   val usersProp = UsersProp(maxUsers = maxUsers, webcamsOnlyForModerator = webcamsOnlyForModerator,
     guestPolicy = guestPolicy)
   val metadataProp = new MetadataProp(metadata)
diff --git a/bbb-common-message/src/test/scala/org/bigbluebutton/common2/messages/DeserializerTests.scala b/bbb-common-message/src/test/scala/org/bigbluebutton/common2/messages/DeserializerTests.scala
index b3050e3bf264eaee2c50e9779e6c603ba8d3e66d..6eccd3d56cef3de2b3ba6b859085eb7520f941f6 100755
--- a/bbb-common-message/src/test/scala/org/bigbluebutton/common2/messages/DeserializerTests.scala
+++ b/bbb-common-message/src/test/scala/org/bigbluebutton/common2/messages/DeserializerTests.scala
@@ -1,12 +1,11 @@
 package org.bigbluebutton.common2.messages
 
 import com.fasterxml.jackson.databind.JsonNode
-import org.bigbluebutton.common2.messages.MessageBody.CreateMeetingReqMsgBody
+import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.common2.util.JsonUtil
-import org.bigbluebutton.common2.{TestFixtures, UnitSpec2}
-
-import scala.util.{Failure, Success}
+import org.bigbluebutton.common2.{ TestFixtures, UnitSpec2 }
 
+import scala.util.{ Failure, Success }
 
 class DeserializerTests extends UnitSpec2 with TestFixtures {
 
@@ -28,7 +27,7 @@ class DeserializerTests extends UnitSpec2 with TestFixtures {
     println(map)
     map match {
       case Success(envJsNodeMsg) => assert(envJsNodeMsg.core.isInstanceOf[JsonNode])
-      case Failure(ex) => fail("Failed to decode json message " + ex)
+      case Failure(ex)           => fail("Failed to decode json message " + ex)
     }
   }
 
@@ -46,11 +45,12 @@ class DeserializerTests extends UnitSpec2 with TestFixtures {
     println(map)
 
     map match {
-      case Success(envJsNodeMsg) => assert(envJsNodeMsg.core.isInstanceOf[JsonNode])
-        val createMeetingReqMsg = Deserializer.toCreateMeetingReqMsg(envJsNodeMsg.envelope, envJsNodeMsg.core)
-        createMeetingReqMsg match {
+      case Success(envJsNodeMsg) =>
+        assert(envJsNodeMsg.core.isInstanceOf[JsonNode])
+        val (msg, exception) = Deserializer.toBbbCommonMsg[CreateMeetingReqMsg](envJsNodeMsg.core)
+        msg match {
           case Some(cmrq) => assert(cmrq.isInstanceOf[CreateMeetingReqMsg])
-          case None => fail("Failed to decode CreateMeetingReqMsg")
+          case None       => fail("Failed to decode CreateMeetingReqMsg")
         }
       case Failure(ex) => fail("Failed to decode json message " + ex)
     }
@@ -71,11 +71,12 @@ class DeserializerTests extends UnitSpec2 with TestFixtures {
     println(map)
 
     map match {
-      case Success(envJsNodeMsg) => assert(envJsNodeMsg.core.isInstanceOf[JsonNode])
+      case Success(envJsNodeMsg) =>
+        assert(envJsNodeMsg.core.isInstanceOf[JsonNode])
         val (msg, exception) = Deserializer.toBbbCommonMsg[CreateMeetingReqMsg](envJsNodeMsg.core)
         msg match {
           case Some(cmrq) => assert(cmrq.isInstanceOf[CreateMeetingReqMsg])
-          case None => fail("Should have successfully decoded CreateMeetingReqMsg ")
+          case None       => fail("Should have successfully decoded CreateMeetingReqMsg ")
         }
       case Failure(ex) => fail("Failed to decode json message " + ex)
     }
@@ -103,7 +104,7 @@ class DeserializerTests extends UnitSpec2 with TestFixtures {
     val (result, error) = Deserializer.toBbbCoreMessageFromClient(jsonMsg)
     result match {
       case Some(msg) => assert(msg.header.name == "foo")
-      case None => fail("Should have deserialized message but failed with error: " + error)
+      case None      => fail("Should have deserialized message but failed with error: " + error)
     }
   }
 }
diff --git a/bbb-common-message/src/test/scala/org/bigbluebutton/common2/util/JsonUtilTest.scala b/bbb-common-message/src/test/scala/org/bigbluebutton/common2/util/JsonUtilTest.scala
index f701a432de2a92dc520fe585b4b17ec5b00d13ae..7d65d24d2b53db9acc5d623cb40ec2640a6676e1 100755
--- a/bbb-common-message/src/test/scala/org/bigbluebutton/common2/util/JsonUtilTest.scala
+++ b/bbb-common-message/src/test/scala/org/bigbluebutton/common2/util/JsonUtilTest.scala
@@ -1,14 +1,12 @@
 package org.bigbluebutton.common2.util
 
-import org.bigbluebutton.common2.{TestFixtures, UnitSpec2}
-import org.bigbluebutton.common2.messages._
+import org.bigbluebutton.common2.{ TestFixtures, UnitSpec2 }
+import org.bigbluebutton.common2.msgs._
 
 import scala.collection.immutable.List
 import com.fasterxml.jackson.databind.JsonNode
-import org.bigbluebutton.common2.messages.MessageBody.ValidateAuthTokenReqMsgBody
-
-import scala.util.{Failure, Success}
 
+import scala.util.{ Failure, Success }
 
 case class Person(name: String, age: Int)
 case class Group(name: String, persons: Seq[Person], leader: Person)
@@ -26,7 +24,7 @@ class JsonUtilTest extends UnitSpec2 with TestFixtures {
     // map: Map[String,Seq[Int]] = Map(a -> List(1, 2), b -> List(3, 4, 5), c -> List())
     println(map)
     map match {
-      case Success(a) => assert(a.values.size == 3)
+      case Success(a)  => assert(a.values.size == 3)
       case Failure(ex) => fail("Failed to decode json message")
     }
   }
@@ -38,7 +36,7 @@ class JsonUtilTest extends UnitSpec2 with TestFixtures {
     val jeroen = Person("Jeroen", 26)
     val martin = Person("Martin", 54)
 
-    val originalGroup = Group("Scala ppl", Seq(jeroen,martin), martin)
+    val originalGroup = Group("Scala ppl", Seq(jeroen, martin), martin)
     // originalGroup: Group = Group(Scala ppl,List(Person(Jeroen,26), Person(Martin,54)),Person(Martin,54))
     println(originalGroup)
 
@@ -52,7 +50,7 @@ class JsonUtilTest extends UnitSpec2 with TestFixtures {
   }
 
   "JsonUtil" should "unmarshall a ValidateAuthTokenReq" in {
-    val header: BbbCoreHeaderWithMeetingId = new BbbCoreHeaderWithMeetingId("foo", "mId")
+    val header: BbbClientMsgHeader = new BbbClientMsgHeader("foo", "mId", "uId")
     val body: ValidateAuthTokenReqMsgBody = new ValidateAuthTokenReqMsgBody(userId = "uId", authToken = "myToken")
     val msg: ValidateAuthTokenReqMsg = new ValidateAuthTokenReqMsg(header, body)
     val json = JsonUtil.toJson(msg)
diff --git a/bbb-common-web/build.sbt b/bbb-common-web/build.sbt
index 11ff1b07e84f78a5e330ea98ddf8763bd2cb50aa..0519059e3804bb645328d651ae678ce0ef83224d 100755
--- a/bbb-common-web/build.sbt
+++ b/bbb-common-web/build.sbt
@@ -1,19 +1,23 @@
-name := "bbb-common-web"
-
-organization := "org.bigbluebutton"
-
-version := "0.0.2-SNAPSHOT"
-
-scalaVersion  := "2.12.6"
-
-scalacOptions ++= Seq(
-  "-unchecked",
-  "-deprecation",
-  "-Xlint",
-  "-Ywarn-dead-code",
-  "-language:_",
-  "-target:jvm-1.8",
-  "-encoding", "UTF-8"
+import org.bigbluebutton.build._
+
+version := "0.0.3-SNAPSHOT"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
 )
 
 // We want to have our jar files in lib_managed dir.
@@ -25,82 +29,8 @@ testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console",
 
 testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
 
-val akkaVersion  = "2.5.14"
-
-// https://mvnrepository.com/artifact/org.scala-lang/scala-library
-libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value
-// https://mvnrepository.com/artifact/org.scala-lang/scala-compiler
-libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-actor_2.12" % akkaVersion
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-slf4j_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-slf4j_2.12" % akkaVersion
-
-// https://mvnrepository.com/artifact/com.github.etaty/rediscala_2.12
-libraryDependencies += "com.github.etaty" % "rediscala_2.12" % "1.8.0"
-
-libraryDependencies += "com.softwaremill.quicklens" %% "quicklens" % "1.4.11"
-
-libraryDependencies += "org.bigbluebutton" % "bbb-common-message_2.12" % "0.0.19-SNAPSHOT"
-// https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-scala_2.12
-libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala_2.12" % "2.9.6"
-
-libraryDependencies += "redis.clients" % "jedis" % "2.9.0"
-libraryDependencies += "com.google.code.gson" % "gson" % "2.8.5"
-
-// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
-libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.7"
-libraryDependencies += "commons-io" % "commons-io" % "2.6"
-libraryDependencies += "org.apache.commons" % "commons-pool2" % "2.6.0"
-libraryDependencies += "com.zaxxer" % "nuprocess" % "1.2.4"
-
-// https://mvnrepository.com/artifact/org.jodconverter/jodconverter-core
-libraryDependencies += "org.jodconverter" % "jodconverter-local" % "4.2.0"
-
-// https://mvnrepository.com/artifact/org.libreoffice/unoil
-libraryDependencies += "org.libreoffice" % "unoil" % "5.4.2"
-
-// https://mvnrepository.com/artifact/org.libreoffice/ridl
-libraryDependencies += "org.libreoffice" % "ridl" % "5.4.2"
-
-// https://mvnrepository.com/artifact/org.libreoffice/juh
-libraryDependencies += "org.libreoffice" % "juh" % "5.4.2"
-
-// https://mvnrepository.com/artifact/org.libreoffice/jurt
-libraryDependencies += "org.libreoffice" % "jurt" % "5.4.2"
-
-
-libraryDependencies += "org.apache.poi" % "poi-ooxml" % "3.17"
-
-libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.25"
-
-// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
-libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.5.6"
-// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpasyncclient
-libraryDependencies += "org.apache.httpcomponents" % "httpasyncclient" % "4.1.4"
-
-libraryDependencies += "org.freemarker" % "freemarker" % "2.3.28"
-libraryDependencies += "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.6"
-// https://mvnrepository.com/artifact/org.codehaus.woodstox/woodstox-core-asl
-libraryDependencies += "org.codehaus.woodstox" % "woodstox-core-asl" % "4.4.1"
-
-libraryDependencies += "org.pegdown" % "pegdown" % "1.4.0" % "test"
-libraryDependencies += "junit" % "junit" % "4.12" % "test"
-libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
-// https://mvnrepository.com/artifact/org.mockito/mockito-core
-libraryDependencies += "org.mockito" % "mockito-core" % "2.7.12" % "test"
-libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.1" % "test"
-libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
-
-// https://mvnrepository.com/artifact/com.typesafe.akka/akka-testkit_2.12
-libraryDependencies += "com.typesafe.akka" % "akka-testkit_2.12" % akkaVersion % "test"
-
-// https://mvnrepository.com/artifact/org.scala-lang.modules/scala-xml_2.12
-libraryDependencies += "org.scala-lang.modules" % "scala-xml_2.12" % "1.1.0"
-
-
-seq(Revolver.settings: _*)
+Seq(Revolver.settings: _*)
+lazy val commonWeb = (project in file(".")).settings(name := "bbb-common-web", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
 //-----------
 // Packaging
@@ -120,12 +50,12 @@ crossPaths := false
 // This forbids including Scala related libraries into the dependency
 autoScalaLibrary := false
 
-/***************************
-* When developing, change the version above to x.x.x-SNAPSHOT then use the file resolver to
-* publish to the local maven repo using "sbt publish"
-*/
+/** *************************
+  * When developing, change the version above to x.x.x-SNAPSHOT then use the file resolver to
+  * publish to the local maven repo using "sbt publish"
+  */
 // Uncomment this to publish to local maven repo while commenting out the nexus repo
-publishTo := Some(Resolver.file("file",  new File(Path.userHome.absolutePath+"/.m2/repository")))
+publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath + "/.m2/repository")))
 
 
 // Comment this out when publishing to local maven repo using SNAPSHOT version.
@@ -150,16 +80,14 @@ pomExtra := (
     <url>git@github.com:bigbluebutton/bigbluebutton.git</url>
     <connection>scm:git:git@github.com:bigbluebutton/bigbluebutton.git</connection>
   </scm>
-  <developers>
-    <developer>
-      <id>ritzalam</id>
-      <name>Richard Alam</name>
-      <url>http://www.bigbluebutton.org</url>
-    </developer>
-  </developers>)
-  
+    <developers>
+      <developer>
+        <id>ritzalam</id>
+        <name>Richard Alam</name>
+        <url>http://www.bigbluebutton.org</url>
+      </developer>
+    </developers>)
+
 licenses := Seq("LGPL-3.0" -> url("http://opensource.org/licenses/LGPL-3.0"))
 
 homepage := Some(url("http://www.bigbluebutton.org"))
-  
-
diff --git a/bbb-common-web/deploy.sh b/bbb-common-web/deploy.sh
index 948f5634178c0655544d5ab9148e6df8cc177ffc..f829bc13dc598da480ee4e512a87c9436925a359 100755
--- a/bbb-common-web/deploy.sh
+++ b/bbb-common-web/deploy.sh
@@ -1,3 +1 @@
-sbt clean
-sbt publish publishLocal
-
+sbt clean publish publishLocal
diff --git a/bbb-common-web/project/Build.scala b/bbb-common-web/project/Build.scala
deleted file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/bbb-common-web/project/Dependencies.scala b/bbb-common-web/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..11f02264ce17223db982de1bb0ef02a5c983b1cb
--- /dev/null
+++ b/bbb-common-web/project/Dependencies.scala
@@ -0,0 +1,103 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+    val junit = "4.12"
+    val junitInterface = "0.11"
+    val scalactic = "3.0.3"
+
+    // Libraries
+    val akkaVersion = "2.5.17"
+    val gson = "2.8.5"
+    val jackson = "2.9.7"
+    val freemaker = "2.3.28"
+    val apacheHttp = "4.5.6"
+    val apacheHttpAsync = "4.1.4"
+
+    // Office and document conversion
+    val apacheOffice = "4.0.0"
+    val jodConverter = "4.2.1"
+    val apachePoi = "3.17"
+    val nuProcess = "1.2.4"
+    val libreOffice = "5.4.2"
+
+    // Apache Commons
+    val lang = "3.8.1"
+    val io = "2.6"
+    val pool = "2.6.0"
+
+    // BigBlueButton
+    val bbbCommons = "0.0.20-SNAPSHOT"
+
+    // Test
+    val scalaTest = "3.0.5"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaCompiler = "org.scala-lang" % "scala-compiler" % Versions.scala
+
+    val akkaActor = "com.typesafe.akka" % "akka-actor_2.12" % Versions.akkaVersion
+    val akkaSl4fj = "com.typesafe.akka" % "akka-slf4j_2.12" % Versions.akkaVersion % "runtime"
+
+    val googleGson = "com.google.code.gson" % "gson" % Versions.gson
+    val jacksonModule = "com.fasterxml.jackson.module" %% "jackson-module-scala" % Versions.jackson
+    val jacksonXml = "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % Versions.jackson
+    val freeMaker = "org.freemarker" % "freemarker" % Versions.freemaker
+    val apacheHttp = "org.apache.httpcomponents" % "httpclient" % Versions.apacheHttp
+    val apacheHttpAsync = "org.apache.httpcomponents" % "httpasyncclient" % Versions.apacheHttpAsync
+
+    val poiXml = "org.apache.poi" % "poi-ooxml" % Versions.apachePoi
+    val jodConverter = "org.jodconverter" % "jodconverter-local" % Versions.jodConverter
+    val nuProcess = "com.zaxxer" % "nuprocess" % Versions.nuProcess
+
+    val officeUnoil = "org.libreoffice" % "unoil" % Versions.libreOffice
+    val officeRidl = "org.libreoffice" % "ridl" % Versions.libreOffice
+    val officeJuh = "org.libreoffice" % "juh" % Versions.libreOffice
+    val officejurt = "org.libreoffice" % "jurt" % Versions.libreOffice
+
+    val apacheLang = "org.apache.commons" % "commons-lang3" % Versions.lang
+    val apacheIo = "commons-io" % "commons-io" % Versions.io
+    val apachePool2 = "org.apache.commons" % "commons-pool2" % Versions.pool
+
+    val bbbCommons = "org.bigbluebutton" % "bbb-common-message_2.12" % Versions.bbbCommons
+  }
+
+  object Test {
+    val scalaTest = "org.scalatest" %% "scalatest" % Versions.scalaTest % "test"
+    val junit = "junit" % "junit" % Versions.junit % "test"
+    val junitInteface = "com.novocode" % "junit-interface" % Versions.junitInterface % "test"
+    val scalactic = "org.scalactic" % "scalactic_2.12" % Versions.scalactic % "test"
+  }
+
+  val testing = Seq(
+    Test.scalaTest,
+    Test.junit,
+    Test.junitInteface,
+    Test.scalactic)
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaCompiler,
+    Compile.akkaActor,
+    Compile.akkaSl4fj,
+    Compile.googleGson,
+    Compile.jacksonModule,
+    Compile.jacksonXml,
+    Compile.freeMaker,
+    Compile.apacheHttp,
+    Compile.apacheHttpAsync,
+    Compile.poiXml,
+    Compile.jodConverter,
+    Compile.nuProcess,
+    Compile.apacheLang,
+    Compile.apacheIo,
+    Compile.apachePool2,
+    Compile.bbbCommons) ++ testing
+}
diff --git a/bbb-common-web/project/build.properties b/bbb-common-web/project/build.properties
index a6e117b61042ee81c62ba3a0fc5210d9502944df..2e6e3d24608ee15e892ed3b16d84224f7667e808 100755
--- a/bbb-common-web/project/build.properties
+++ b/bbb-common-web/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=1.2.6
\ No newline at end of file
diff --git a/bbb-common-web/project/plugins.sbt b/bbb-common-web/project/plugins.sbt
index b91f89e4a637ce583af1b0e09615d2f9044e033b..4eb70b26c5aeae53a81b4c122607bda9733ec175 100755
--- a/bbb-common-web/project/plugins.sbt
+++ b/bbb-common-web/project/plugins.sbt
@@ -2,9 +2,7 @@ addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
-
-addSbtPlugin("com.artima.supersafe" % "sbtplugin" % "1.1.7")
+addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1")
 
 addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
 
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java
index b55af510e8eba9d48d0700d4fe44f72b52dbdc8b..825d0deea84dd58dc6a186cf6ab21bc84c37c299 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java
@@ -48,7 +48,6 @@ import org.bigbluebutton.api.domain.RegisteredUser;
 import org.bigbluebutton.api.domain.User;
 import org.bigbluebutton.api.domain.UserSession;
 import org.bigbluebutton.api.messaging.MessageListener;
-import org.bigbluebutton.api.messaging.RedisStorageService;
 import org.bigbluebutton.api.messaging.converters.messages.DestroyMeetingMessage;
 import org.bigbluebutton.api.messaging.converters.messages.EndMeetingMessage;
 import org.bigbluebutton.api.messaging.messages.CreateBreakoutRoom;
@@ -77,6 +76,7 @@ import org.bigbluebutton.api.messaging.messages.UserStatusChanged;
 import org.bigbluebutton.api.messaging.messages.UserUnsharedWebcam;
 import org.bigbluebutton.api2.IBbbWebApiGWApp;
 import org.bigbluebutton.api2.domain.UploadedTrack;
+import org.bigbluebutton.common2.redis.RedisStorageService;
 import org.bigbluebutton.presentation.PresentationUrlDownloadService;
 import org.bigbluebutton.web.services.RegisteredUserCleanupTimerTask;
 import org.bigbluebutton.web.services.callback.CallbackUrlService;
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/MessageDistributor.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/MessageDistributor.java
index d6f2837b40f3c7a4bc0df3744d340a689531b39a..007d16d51d374da794faf6dcc5027571841e3ea3 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/MessageDistributor.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/MessageDistributor.java
@@ -5,23 +5,23 @@ import java.util.Set;
 import org.bigbluebutton.api.messaging.messages.IMessage;
 
 public class MessageDistributor {
-  private ReceivedMessageHandler handler;
-  private Set<MessageListener> listeners;
+    private ReceivedMessageHandler handler;
+    private Set<MessageListener> listeners;
 
-  public void setMessageListeners(Set<MessageListener> listeners) {
-    this.listeners = listeners;
-  }
+    public void setMessageListeners(Set<MessageListener> listeners) {
+        this.listeners = listeners;
+    }
 
-  public void setMessageHandler(ReceivedMessageHandler handler) {
-    this.handler = handler;
-    if (handler != null) {
-      handler.setMessageDistributor(this);
+    public void setMessageHandler(ReceivedMessageHandler handler) {
+        this.handler = handler;
+        if (handler != null) {
+            handler.setMessageDistributor(this);
+        }
     }
-  }
 
-  public void notifyListeners(IMessage message) {
-    for (MessageListener listener : listeners) {
-      listener.handle(message);
+    public void notifyListeners(IMessage message) {
+        for (MessageListener listener : listeners) {
+            listener.handle(message);
+        }
     }
-  }
 }
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/ReceivedMessageHandler.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/ReceivedMessageHandler.java
index 38690c4b1e1810135b329130eb6b436bfd8fd3c0..9a1171de745952d9d915efabcd3490a3328a8ab6 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/ReceivedMessageHandler.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/ReceivedMessageHandler.java
@@ -11,65 +11,65 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ReceivedMessageHandler implements IReceivedOldMessageHandler {
-  private static Logger log = LoggerFactory.getLogger(ReceivedMessageHandler.class);
+    private static Logger log = LoggerFactory.getLogger(ReceivedMessageHandler.class);
 
-  private BlockingQueue<ReceivedMessage> receivedMessages = new LinkedBlockingQueue<>();
+    private BlockingQueue<ReceivedMessage> receivedMessages = new LinkedBlockingQueue<>();
 
-  private volatile boolean processMessage = false;
+    private volatile boolean processMessage = false;
 
-  private final Executor msgProcessorExec = Executors.newSingleThreadExecutor();
-  private final Executor runExec = Executors.newSingleThreadExecutor();
+    private final Executor msgProcessorExec = Executors.newSingleThreadExecutor();
+    private final Executor runExec = Executors.newSingleThreadExecutor();
 
-  private MessageDistributor outGW;
+    private MessageDistributor outGW;
 
-  public void stop() {
-    processMessage = false;
-  }
+    public void stop() {
+        processMessage = false;
+    }
 
-  public void start() {
-    log.info("Ready to handle messages from Redis pubsub!");
+    public void start() {
+        log.info("Ready to handle messages from Redis pubsub!");
+
+        try {
+            processMessage = true;
+
+            Runnable messageProcessor = new Runnable() {
+                public void run() {
+                    while (processMessage) {
+                        try {
+                            ReceivedMessage msg = receivedMessages.take();
+                            processMessage(msg);
+                        } catch (InterruptedException e) {
+                            log.warn("Error while taking received message from queue.");
+                        }
+                    }
+                }
+            };
+            msgProcessorExec.execute(messageProcessor);
+        } catch (Exception e) {
+            log.error("Error subscribing to channels: {}", e);
+        }
+    }
 
-    try {
-      processMessage = true;
+    private void notifyListeners(IMessage message) {
+        outGW.notifyListeners(message);
+    }
 
-      Runnable messageProcessor = new Runnable() {
-        public void run() {
-          while (processMessage) {
-            try {
-              ReceivedMessage msg = receivedMessages.take();
-              processMessage(msg);
-            } catch (InterruptedException e) {
-              log.warn("Error while taking received message from queue.");
+    private void processMessage(final ReceivedMessage msg) {
+        Runnable task = new Runnable() {
+            public void run() {
+                notifyListeners(msg.getMessage());
             }
-          }
-        }
-      };
-      msgProcessorExec.execute(messageProcessor);
-    } catch (Exception e) {
-      log.error("Error subscribing to channels: {}", e);
+        };
+
+        runExec.execute(task);
+    }
+
+    public void handleMessage(IMessage message) {
+        ReceivedMessage rm = new ReceivedMessage(message);
+        receivedMessages.add(rm);
+    }
+
+    public void setMessageDistributor(MessageDistributor outGW) {
+        this.outGW = outGW;
     }
-  }
-
-  private void notifyListeners(IMessage message) {
-    outGW.notifyListeners(message);
-  }
-
-  private void processMessage(final ReceivedMessage msg) {
-    Runnable task = new Runnable() {
-      public void run() {
-        notifyListeners(msg.getMessage());
-      }
-    };
-
-    runExec.execute(task);
-  }
-
-  public void handleMessage(IMessage message) {
-    ReceivedMessage rm = new ReceivedMessage(message);
-    receivedMessages.add(rm);
-  }
-
-  public void setMessageDistributor(MessageDistributor outGW) {
-    this.outGW = outGW;
-  }
 }
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/RedisStorageService.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/RedisStorageService.java
deleted file mode 100755
index 180c95e5ce1517133df3bf5fb72d55aa967a6680..0000000000000000000000000000000000000000
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/RedisStorageService.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bigbluebutton.api.messaging;
-
-import java.util.Map;
-
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.Protocol;
-
-public class RedisStorageService {
-  private static Logger log = LoggerFactory.getLogger(RedisStorageService.class);
-
-  private JedisPool redisPool;
-  private String host;
-  private int port;
-
-  public void stop() {
-
-  }
-
-  public void start() {
-    // Set the name of this client to be able to distinguish when doing
-    // CLIENT LIST on redis-cli
-    redisPool = new JedisPool(new GenericObjectPoolConfig<Object>(), host, port, Protocol.DEFAULT_TIMEOUT, null,
-      Protocol.DEFAULT_DATABASE, "BbbRed5AppsPub");
-  }
-
-  public void recordMeetingInfo(String meetingId, Map<String, String> info) {
-    Jedis jedis = redisPool.getResource();
-    try {
-      if (log.isDebugEnabled()) {
-        for (Map.Entry<String,String> entry : info.entrySet()) {
-          log.debug("Storing metadata {} = {}", entry.getKey(), entry.getValue());
-        }
-      }
-
-      log.debug("Saving metadata in {}", meetingId);
-      jedis.hmset("meeting:info:" + meetingId, info);
-    } catch (Exception e) {
-      log.warn("Cannot record the info meeting: {}", meetingId, e);
-    } finally {
-      jedis.close();
-    }
-  }
-
-  public void recordBreakoutInfo(String meetingId, Map<String, String> breakoutInfo) {
-    Jedis jedis = redisPool.getResource();
-    try {
-      log.debug("Saving breakout metadata in {}", meetingId);
-      jedis.hmset("meeting:breakout:" + meetingId, breakoutInfo);
-    } catch (Exception e) {
-      log.warn("Cannot record the info meeting: {}", meetingId, e);
-    } finally {
-      jedis.close();
-    }
-  }
-
-  public void addBreakoutRoom(String parentId, String breakoutId) {
-    Jedis jedis = redisPool.getResource();
-    try {
-
-      log.debug("Saving breakout room for meeting {}", parentId);
-      jedis.sadd("meeting:breakout:rooms:" + parentId, breakoutId);
-    } catch (Exception e) {
-      log.warn("Cannot record the info meeting:" + parentId, e);
-    } finally {
-      jedis.close();
-    }
-  }
-
-  public void removeMeeting(String meetingId) {
-    Jedis jedis = redisPool.getResource();
-    try {
-      jedis.del("meeting-" + meetingId);
-      jedis.srem("meetings", meetingId);
-    } finally {
-      jedis.close();
-    }
-  }
-
-  public void setHost(String host) {
-    this.host = host;
-  }
-
-  public void setPort(int port) {
-    this.port = port;
-  }
-}
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/web/services/RedisStorageService.java b/bbb-common-web/src/main/java/org/bigbluebutton/web/services/RedisStorageService.java
deleted file mode 100755
index 3a45aedfd144ec9a6803672d81432e1c21420f7d..0000000000000000000000000000000000000000
--- a/bbb-common-web/src/main/java/org/bigbluebutton/web/services/RedisStorageService.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-package org.bigbluebutton.web.services;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.bigbluebutton.api.domain.Poll;
-
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-
-public class RedisStorageService implements IStorageService{
-	JedisPool jedisPool;
-
-	private static final String SEPARATOR = ":";
-	private static final String ID_SEED = "nextID";
-
-	/* Meeting Patterns */
-	private static final String MEETING = "meeting";
-	private static final String POLL = "poll";
-	private static final String POLL_ANSWER = "answer";
-	private static final String POLL_RESULTS = "results";
-
-	/*
-meeting:<id>:poll:list [1,2,3] <-- list
-meeting:<id>:poll:<pollid> title, date <-- hash
-meeting:<id>:poll:<pollid>:answer:list [1,2,3] <-- list
-meeting:<id>:poll:<pollid>:answer:<answerid> answertext <-- key/value
-
-meeting:<id>:poll:<pollid>:answer:<answerid>:results [<userid>|1] <-- Set
-	*/
-
-	public String generatePollID(String meetingID){
-		Jedis jedis = (Jedis) jedisPool.getResource();
-		String pattern = getPollRedisPattern(meetingID);
-		String pollID = Long.toString(jedis.incr(pattern + SEPARATOR + ID_SEED));
-		jedisPool.returnResource(jedis);
-		return pollID;
-	}
-
-	public String generatePollAnswerID(String meetingID){
-		Jedis jedis = jedisPool.getResource();
-		String pattern = getPollRedisPattern(meetingID);
-		String pollID = Long.toString(jedis.incr(pattern + SEPARATOR + POLL_ANSWER + SEPARATOR + ID_SEED));
-		jedisPool.returnResource(jedis);
-		return pollID;
-	}
-
-	public void storePoll(Poll p){
-		Jedis jedis = jedisPool.getResource();
-		String pattern = getPollRedisPattern(p.getMeetingID());
-
-		HashMap<String,String> pollMap = p.toMap();
-		jedis.hmset(pattern + SEPARATOR + p.getPollID(), pollMap);
-		jedisPool.returnResource(jedis);
-	}
-
-	public void storePollAnswers(String meetingID, String pollID, Map<String,String> answers){
-		Jedis jedis = jedisPool.getResource();
-		String pattern = getPollRedisPattern(meetingID);
-
-		//HashMap<String,String> pollMap = p.toMap();
-		//jedis.hmset(pattern + SEPARATOR + p.getPollID + SEPARATOR + POLL_ANSWER + SEPARATOR + ID_SEED, pollMap);
-		//jedisPool.returnResource(jedis);	
-	}
-
-	private String getPollRedisPattern(String meetingID){
-		return MEETING + SEPARATOR + meetingID + SEPARATOR + POLL;
-	}
-
-	public void setJedisPool(JedisPool jedisPool){
-		this.jedisPool = jedisPool;
-	}
-}
\ No newline at end of file
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala
index 053c62ad567117e2120f8eb817a85ae55db7b081..6d62c007f4b22d54d1943c9533b207da058a0c62 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala
@@ -5,12 +5,14 @@ import akka.actor.ActorSystem
 import akka.event.Logging
 import org.bigbluebutton.api.messaging.converters.messages._
 import org.bigbluebutton.api2.bus._
-import org.bigbluebutton.api2.endpoint.redis.{ AppsRedisSubscriberActor, MessageSender, RedisPublisher }
+import org.bigbluebutton.api2.endpoint.redis.{ WebRedisSubscriberActor }
+import org.bigbluebutton.common2.redis.MessageSender
 import org.bigbluebutton.api2.meeting.{ OldMeetingMsgHdlrActor, RegisterUser }
 import org.bigbluebutton.common2.domain._
 import org.bigbluebutton.presentation.messages._
-
 import scala.concurrent.duration._
+import org.bigbluebutton.common2.redis._
+import org.bigbluebutton.common2.bus._
 
 class BbbWebApiGWApp(
   val oldMessageReceivedGW:        OldMessageReceivedGW,
@@ -24,10 +26,8 @@ class BbbWebApiGWApp(
 
   val log = Logging(system, getClass)
 
-  log.debug("*********** meetingManagerChannel = " + meetingManagerChannel)
-
   private val jsonMsgToAkkaAppsBus = new JsonMsgToAkkaAppsBus
-  private val redisPublisher = new RedisPublisher(system)
+  private val redisPublisher = new RedisPublisher(system, "BbbWebPub")
   private val msgSender: MessageSender = new MessageSender(redisPublisher)
   private val messageSenderActorRef = system.actorOf(MessageSenderActor.props(msgSender), "messageSenderActor")
 
@@ -54,8 +54,7 @@ class BbbWebApiGWApp(
 
   msgToAkkaAppsEventBus.subscribe(msgToAkkaAppsToJsonActor, toAkkaAppsChannel)
 
-  private val appsRedisSubscriberActor = system.actorOf(
-    AppsRedisSubscriberActor.props(receivedJsonMsgBus, oldMessageEventBus), "appsRedisSubscriberActor")
+  private val appsRedisSubscriberActor = system.actorOf(WebRedisSubscriberActor.props(system, receivedJsonMsgBus, oldMessageEventBus), "appsRedisSubscriberActor")
 
   private val receivedJsonMsgHdlrActor = system.actorOf(
     ReceivedJsonMsgHdlrActor.props(msgFromAkkaAppsEventBus), "receivedJsonMsgHdlrActor")
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/SystemConfiguration.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/SystemConfiguration.scala
index 0eb67da98170ac2b5304922e745ffcd835351719..71d5d402c9dbc462ff2206677a22e5912f4ed5eb 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/SystemConfiguration.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/SystemConfiguration.scala
@@ -3,17 +3,11 @@ package org.bigbluebutton.api2
 import com.typesafe.config.ConfigFactory
 
 import scala.util.Try
+import org.bigbluebutton.common2.redis.RedisConfiguration
 
-trait SystemConfiguration {
-  val config = ConfigFactory.load("bbb-web")
+trait SystemConfiguration extends RedisConfiguration {
+  override val config = ConfigFactory.load("bbb-web")
 
-  lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
-  lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
-  lazy val redisPassword = Try(config.getString("redis.password")).getOrElse("")
-
-  lazy val toAkkaAppsRedisChannel = Try(config.getString("redis.toAkkaAppsRedisChannel")).getOrElse("to-akka-apps-redis-channel")
-  lazy val fromAkkaAppsRedisChannel = Try(config.getString("redis.fromAkkaAppsRedisChannel")).getOrElse("from-akka-apps-redis-channel")
-  lazy val meetingManagerChannel = Try(config.getString("eventBus.meetingManagerChannel")).getOrElse("FOOOOOOOOO")
   lazy val fromAkkaAppsChannel = Try(config.getString("eventBus.fromAkkaAppsChannel")).getOrElse("from-akka-apps-channel")
   lazy val toAkkaAppsChannel = Try(config.getString("eventBus.toAkkaAppsChannel")).getOrElse("to-akka-apps-channel")
   lazy val fromClientChannel = Try(config.getString("eventBus.fromClientChannel")).getOrElse("from-client-channel")
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MessageSenderActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MessageSenderActor.scala
index f4dc981cc96c2d79547f5d62693aa8da83c33558..e21612025c28d43587c0f715fe81455e67ffd03b 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MessageSenderActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/MessageSenderActor.scala
@@ -4,7 +4,7 @@ import java.io.{PrintWriter, StringWriter}
 
 import akka.actor.SupervisorStrategy.Resume
 import akka.actor.{Actor, ActorLogging, OneForOneStrategy, Props}
-import org.bigbluebutton.api2.endpoint.redis.MessageSender
+import org.bigbluebutton.common2.redis.MessageSender
 import scala.concurrent.duration._
 
 object MessageSenderActor {
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageJsonReceiverActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageJsonReceiverActor.scala
index f996ad30ef5c87f4b417d238639ffc3facd34f76..ab5af661bf3f1fec0935d364ce2e9c027538813d 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageJsonReceiverActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/OldMessageJsonReceiverActor.scala
@@ -1,6 +1,7 @@
 package org.bigbluebutton.api2.bus
 
-import akka.actor.{Actor, ActorLogging, Props}
+import akka.actor.{Actor, ActorLogging, Props}
+import org.bigbluebutton.common2.bus.OldReceivedJsonMessage
 
 object OldMessageJsonReceiverActor{
   def props(gw: OldMessageReceivedGW): Props = Props(classOf[OldMessageJsonReceiverActor], gw)
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala
index e63f2d454eecd42ea026bab87933fa10d02dde58..174e4951dfd5fad4a2a6c1dbd980207d78999111 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/bus/ReceivedJsonMsgHdlrActor.scala
@@ -1,6 +1,7 @@
 package org.bigbluebutton.api2.bus
 
 import org.bigbluebutton.api2.SystemConfiguration
+import org.bigbluebutton.common2.bus._
 import org.bigbluebutton.common2.msgs._
 import com.fasterxml.jackson.databind.JsonNode
 import akka.actor.Actor
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/AppsRedisSubscriberActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/AppsRedisSubscriberActor.scala
deleted file mode 100755
index 3b566c6f2f90eedc8969cb7b3346aef349c69a02..0000000000000000000000000000000000000000
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/AppsRedisSubscriberActor.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bigbluebutton.api2.endpoint.redis
-
-import java.io.{PrintWriter, StringWriter}
-import java.net.InetSocketAddress
-
-import akka.actor.SupervisorStrategy.Resume
-import akka.actor.{OneForOneStrategy, Props}
-import redis.api.servers.ClientSetname
-import redis.actors.RedisSubscriberActor
-import redis.api.pubsub.{Message, PMessage}
-import scala.concurrent.duration._
-
-import org.bigbluebutton.api2.SystemConfiguration
-import org.bigbluebutton.api2.bus._
-
-object AppsRedisSubscriberActor extends SystemConfiguration {
-
-  val channels = Seq(fromAkkaAppsRedisChannel)
-  val patterns = Seq("bigbluebutton:from-bbb-apps:*")
-
-  def props(jsonMsgBus: JsonMsgFromAkkaAppsBus, oldMessageEventBus: OldMessageEventBus): Props =
-    Props(classOf[AppsRedisSubscriberActor], jsonMsgBus, oldMessageEventBus,
-      redisHost, redisPort,
-      channels, patterns).withDispatcher("akka.rediscala-subscriber-worker-dispatcher")
-}
-
-class AppsRedisSubscriberActor(jsonMsgBus: JsonMsgFromAkkaAppsBus, oldMessageEventBus: OldMessageEventBus, redisHost: String,
-                               redisPort: Int,
-                               channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
-    extends RedisSubscriberActor(new InetSocketAddress(redisHost, redisPort),
-      channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") }) with SystemConfiguration {
-
-  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
-    case e: Exception => {
-      val sw: StringWriter = new StringWriter()
-      sw.write("An exception has been thrown on AppsRedisSubscriberActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
-      e.printStackTrace(new PrintWriter(sw))
-      log.error(sw.toString())
-      Resume
-    }
-  }
-
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  write(ClientSetname("Red5AppsSub").encodedRequest)
-
-  def onMessage(message: Message) {
-    //log.error(s"SHOULD NOT BE RECEIVING: $message")
-    if (message.channel == fromAkkaAppsRedisChannel) {
-      val receivedJsonMessage = new JsonMsgFromAkkaApps(message.channel, message.data.utf8String)
-      jsonMsgBus.publish(JsonMsgFromAkkaAppsEvent(fromAkkaAppsJsonChannel, receivedJsonMessage))
-    }
-  }
-
-  def onPMessage(pmessage: PMessage) {
-    log.debug(s"RECEIVED:\n ${pmessage.data.utf8String} \n")
-    val receivedJsonMessage = new OldReceivedJsonMessage(pmessage.patternMatched,
-      pmessage.channel, pmessage.data.utf8String)
-
-    oldMessageEventBus.publish(OldIncomingJsonMessage(fromAkkaAppsOldJsonChannel, receivedJsonMessage))
-  }
-}
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisDataStorageActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisDataStorageActor.scala
index 8fb2731d4204bd661b5c1762549593439adf1066..e4d6628018a0a84ee2c596c3b12221c4b1393c86 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisDataStorageActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisDataStorageActor.scala
@@ -1,51 +1,48 @@
 package org.bigbluebutton.api2.endpoint.redis
 
-import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
 import org.bigbluebutton.api2.SystemConfiguration
-import redis.RedisClient
+import org.bigbluebutton.common2.redis.RedisStorageProvider
 
+import akka.actor.Actor
+import akka.actor.ActorLogging
+import akka.actor.ActorSystem
+import akka.actor.Props
 
 case class RecordMeetingInfoMsg(meetingId: String, info: collection.immutable.Map[String, String])
 case class RecordBreakoutInfoMsg(meetingId: String, info: collection.immutable.Map[String, String])
 case class AddBreakoutRoomMsg(parentId: String, breakoutId: String)
 case class RemoveMeetingMsg(meetingId: String)
 
-
 object RedisDataStorageActor {
   def props(system: ActorSystem): Props = Props(classOf[RedisDataStorageActor], system)
 }
 
-class RedisDataStorageActor(val system: ActorSystem) extends Actor with ActorLogging with SystemConfiguration {
-
-  val redis = RedisClient(redisHost, redisPort)(system)
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  redis.clientSetname("BbbWebStore")
+class RedisDataStorageActor(val system: ActorSystem)
+  extends RedisStorageProvider(system, "BbbWebStore")
+  with SystemConfiguration
+  with Actor with ActorLogging {
 
   def receive = {
-    case msg: RecordMeetingInfoMsg => handleRecordMeetingInfoMsg(msg)
+    case msg: RecordMeetingInfoMsg  => handleRecordMeetingInfoMsg(msg)
     case msg: RecordBreakoutInfoMsg => handleRecordBreakoutInfoMsg(msg)
-    case msg: AddBreakoutRoomMsg => handleAddBreakoutRoomMsg(msg)
-    case msg: RemoveMeetingMsg => handleRemoveMeetingMsg(msg)
+    case msg: AddBreakoutRoomMsg    => handleAddBreakoutRoomMsg(msg)
+    case msg: RemoveMeetingMsg      => handleRemoveMeetingMsg(msg)
   }
 
-
   def handleRecordMeetingInfoMsg(msg: RecordMeetingInfoMsg): Unit = {
-    redis.hmset("meeting:info:" + msg.meetingId, msg.info)
+    redis.recordMeetingInfo(msg.meetingId, msg.info.asInstanceOf[java.util.Map[java.lang.String, java.lang.String]]);
   }
 
   def handleRecordBreakoutInfoMsg(msg: RecordBreakoutInfoMsg): Unit = {
-    redis.hmset("meeting:breakout:" + msg.meetingId, msg.info)
+    redis.recordBreakoutInfo(msg.meetingId, msg.info.asInstanceOf[java.util.Map[java.lang.String, java.lang.String]])
   }
 
   def handleAddBreakoutRoomMsg(msg: AddBreakoutRoomMsg): Unit = {
-    redis.sadd("meeting:breakout:rooms:" + msg.parentId, msg.breakoutId)
+    redis.addBreakoutRoom(msg.parentId, msg.breakoutId)
   }
 
   def handleRemoveMeetingMsg(msg: RemoveMeetingMsg): Unit = {
-    redis.del("meeting-" + msg.meetingId)
-    redis.srem("meetings", msg.meetingId)
+    redis.removeMeeting(msg.meetingId)
   }
 
 }
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisPublisher.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisPublisher.scala
deleted file mode 100755
index 23e47ddd06d00f8173032f08c5d585c354129f5f..0000000000000000000000000000000000000000
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/RedisPublisher.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bigbluebutton.api2.endpoint.redis
-
-import akka.actor.ActorSystem
-import akka.event.Logging
-import akka.util.ByteString
-import org.bigbluebutton.api2.SystemConfiguration
-import redis.RedisClient
-
-class RedisPublisher(val system: ActorSystem) extends SystemConfiguration {
-
-  val redis = RedisClient(redisHost, redisPort)(system)
-
-  val log = Logging(system, getClass)
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  redis.clientSetname("BbbWebPub")
-
-  def publish(channel: String, data: String) {
-    //log.debug("PUBLISH TO \n[" + channel + "]: \n " + data + "\n")
-    redis.publish(channel, ByteString(data))
-  }
-
-}
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/WebRedisSubscriberActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/WebRedisSubscriberActor.scala
new file mode 100755
index 0000000000000000000000000000000000000000..bcb2e4b3d26ebbe6d7d9b7573849162364e3f35b
--- /dev/null
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/endpoint/redis/WebRedisSubscriberActor.scala
@@ -0,0 +1,53 @@
+package org.bigbluebutton.api2.endpoint.redis
+
+import org.bigbluebutton.api2.SystemConfiguration
+import org.bigbluebutton.common2.bus._
+import org.bigbluebutton.common2.redis.{ RedisConfiguration, RedisSubscriber, RedisSubscriberProvider }
+
+import akka.actor.ActorSystem
+import akka.actor.Props
+import io.lettuce.core.pubsub.RedisPubSubListener
+
+object WebRedisSubscriberActor extends RedisSubscriber with RedisConfiguration {
+
+  val channels = Seq(fromAkkaAppsRedisChannel)
+  val patterns = Seq("bigbluebutton:from-bbb-apps:*")
+
+  def props(system: ActorSystem, jsonMsgBus: JsonMsgFromAkkaAppsBus, oldMessageEventBus: OldMessageEventBus): Props =
+    Props(
+      classOf[WebRedisSubscriberActor],
+      system, jsonMsgBus, oldMessageEventBus,
+      redisHost, redisPort,
+      channels, patterns).withDispatcher("akka.redis-subscriber-worker-dispatcher")
+}
+
+class WebRedisSubscriberActor(
+  system:     ActorSystem,
+  jsonMsgBus: JsonMsgFromAkkaAppsBus, oldMessageEventBus: OldMessageEventBus, redisHost: String,
+  redisPort: Int,
+  channels:  Seq[String] = Nil, patterns: Seq[String] = Nil)
+  extends RedisSubscriberProvider(system, "BbbWebSub", channels, patterns, null) with SystemConfiguration {
+
+  override def addListener(appChannel: String) {
+    connection.addListener(new RedisPubSubListener[String, String] {
+      def message(channel: String, message: String): Unit = {
+        if (channels.contains(channel)) {
+          val receivedJsonMessage = new JsonMsgFromAkkaApps(channel, message)
+          jsonMsgBus.publish(JsonMsgFromAkkaAppsEvent(fromAkkaAppsJsonChannel, receivedJsonMessage))
+        }
+      }
+      def message(pattern: String, channel: String, message: String): Unit = {
+        log.debug(s"RECEIVED:\n ${message} \n")
+        val receivedJsonMessage = new OldReceivedJsonMessage(pattern, channel, message)
+        oldMessageEventBus.publish(OldIncomingJsonMessage(fromAkkaAppsOldJsonChannel, receivedJsonMessage))
+      }
+      def psubscribed(pattern: String, count: Long): Unit = { log.info("Subscribed to pattern {}", pattern) }
+      def punsubscribed(pattern: String, count: Long): Unit = { log.info("Unsubscribed from pattern {}", pattern) }
+      def subscribed(channel: String, count: Long): Unit = { log.info("Subscribed to pattern {}", channel) }
+      def unsubscribed(channel: String, count: Long): Unit = { log.info("Unsubscribed from channel {}", channel) }
+    })
+  }
+
+  addListener(fromAkkaAppsJsonChannel)
+  subscribe()
+}
diff --git a/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/ParamsUtilTest.scala b/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/ParamsUtilTest.scala
index 6cf5716b067425c1a5a4e5372b58049bc24d2632..460701c67a52074344736bacfea2d03adfbb3066 100755
--- a/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/ParamsUtilTest.scala
+++ b/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/ParamsUtilTest.scala
@@ -1,23 +1,21 @@
-package org.bigbluebutton.api.util
-
-import org.scalatest._
-
-class ParamsUtilTest extends UnitSpec {
-
-  it should "strip out control chars from text" in {
-    val text = "a\u0000b\u0007c\u008fd"
-    val cleaned = ParamsUtil.stripControlChars(text)
-    assert("abcd" == cleaned)
-  }
-
-  it should "complain about invalid chars in meetingId" in {
-    val meetingId = "Demo , Meeting"
-    assert(ParamsUtil.isValidMeetingId(meetingId) == false)
-  }
-
-  it should "accept valid chars in meetingId" in {
-    val meetingId = "Demo Meeting - 123"
-    assert(ParamsUtil.isValidMeetingId(meetingId) == true)
-  }
-
-}
+package org.bigbluebutton.api.util
+
+class ParamsUtilTest extends UnitSpec {
+
+  it should "strip out control chars from text" in {
+    val text = "a\u0000b\u0007c\u008fd"
+    val cleaned = ParamsUtil.stripControlChars(text)
+    assert("abcd" == cleaned)
+  }
+
+  it should "complain about invalid chars in meetingId" in {
+    val meetingId = "Demo , Meeting"
+    assert(ParamsUtil.isValidMeetingId(meetingId) == false)
+  }
+
+  it should "accept valid chars in meetingId" in {
+    val meetingId = "Demo Meeting - 123"
+    assert(ParamsUtil.isValidMeetingId(meetingId) == true)
+  }
+
+}
diff --git a/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/UnitSpec.scala b/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/UnitSpec.scala
index fef2d5a231b50c2ea1597f488d4533cd972b040c..6c5694d0c06fd995a03851556746f84cefeeabc4 100755
--- a/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/UnitSpec.scala
+++ b/bbb-common-web/src/test/scala/org/bigbluebutton/api/util/UnitSpec.scala
@@ -1,8 +1,7 @@
-package org.bigbluebutton.api.util
-
-import org.scalatest.FlatSpec
-import org.scalatest.BeforeAndAfterAll
-import org.scalatest.WordSpec
-import org.scalatest.Matchers
-
-abstract class UnitSpec extends FlatSpec with Matchers with BeforeAndAfterAll
+package org.bigbluebutton.api.util
+
+import org.scalatest.FlatSpec
+import org.scalatest.BeforeAndAfterAll
+import org.scalatest.Matchers
+
+abstract class UnitSpec extends FlatSpec with Matchers with BeforeAndAfterAll
diff --git a/bbb-fsesl-client/build.gradle b/bbb-fsesl-client/build.gradle
deleted file mode 100755
index ad7449677b1d7cfcb3a84f1b5ad1a2b3524472c1..0000000000000000000000000000000000000000
--- a/bbb-fsesl-client/build.gradle
+++ /dev/null
@@ -1,72 +0,0 @@
-apply plugin: 'java'
-apply plugin: 'eclipse'
-
-version = '0.9.0'
-jar.enabled = true
-
-def appName = 'fs-esl-client'
-
-archivesBaseName = appName 
-
-task resolveDeps(type: Copy) {
-    into('lib')
-    from configurations.default
-    from configurations.default.allArtifacts.file
-}
-
-
-artifacts {
-    archives jar
-}
-
-repositories {
-        add(new org.apache.ivy.plugins.resolver.ChainResolver()) {
-        name = 'remote'
-        returnFirst = true
-        add(new org.apache.ivy.plugins.resolver.URLResolver()) {
-                name = "googlecode"
-                addArtifactPattern "http://red5.googlecode.com/svn/repository/[artifact](-[revision]).[ext]"
-                addArtifactPattern "http://red5.googlecode.com/svn/repository/[organisation]/[artifact](-[revision]).[ext]"
-                }
-        add(new org.apache.ivy.plugins.resolver.URLResolver()) {
-                name = "blindside-repos"
-                addArtifactPattern "http://blindside.googlecode.com/svn/repository/[artifact](-[revision]).[ext]"
-                addArtifactPattern "http://blindside.googlecode.com/svn/repository/[organisation]/[artifact](-[revision]).[ext]"
-                }
-        add(new org.apache.ivy.plugins.resolver.URLResolver()) {
-                name = "maven2-central"
-                m2compatible = true
-                addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[module]/[revision]/[artifact](-[revision]).[ext]"
-                addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[artifact]/[revision]/[artifact](-[revision]).[ext]"
-                }
-        add(new org.apache.ivy.plugins.resolver.URLResolver()) {
-                name = "netty-dependency"
-                m2compatible = true
-                addArtifactPattern "http://repository.jboss.org/nexus/content/groups/public-jboss/[organisation]/[module]/[revision]/[artifact](-[revision]).[ext]"
-                addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[artifact]/[revision]/[artifact](-[revision]).[ext]"
-                }
-        }
-        flatDir name: 'fileRepo', dirs: "/home/firstuser/dev/repo"
-}
-
-dependencies {
-	// Logging
-	compile 'ch.qos.logback:logback-core:1.2.3@jar'
-	compile 'ch.qos.logback:logback-classic:1.2.3@jar'
-	compile 'org.slf4j:log4j-over-slf4j:1.7.25@jar' 
-	compile 'org.slf4j:jcl-over-slf4j:1.7.25@jar'
-	compile 'org.slf4j:jul-to-slf4j:1.7.25@jar'
-    compile 'org.slf4j:slf4j-api:1.7.25@jar'
-    
-    testRuntime 'junit:junit:4.8.1.@jar'
-    compile 'org.jboss.netty:netty:3.2.10.Final@jar'
-}
-
-
-uploadArchives {
-    uploadDescriptor = false
-    repositories {
-        add project.repositories.fileRepo
-    }
-}
-
diff --git a/bbb-fsesl-client/build.sbt b/bbb-fsesl-client/build.sbt
index 6cc930898e0964d5da423f80eab0781b35b9b812..4399efc2a4eb945ecde60540463bfe99b225e001 100755
--- a/bbb-fsesl-client/build.sbt
+++ b/bbb-fsesl-client/build.sbt
@@ -1,10 +1,26 @@
-name := "bbb-fsesl-client"
+import org.bigbluebutton.build._
 
 description := "BigBlueButton custom FS-ESL client built on top of FS-ESL Java library."
 
-organization := "org.bigbluebutton"
-
-version := "0.0.6"
+version := "0.0.7-SNAPSHOT"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
+)
 
 // We want to have our jar files in lib_managed dir.
 // This way we'll have the right path when we import
@@ -15,14 +31,8 @@ testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console",
 
 testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
 
-libraryDependencies ++= {
-  Seq(
-	  "org.jboss.netty"          %  "netty"             % "3.2.10.Final",
-	  "junit"                    %  "junit"             % "4.12",
-	  "ch.qos.logback"           %  "logback-classic"   % "1.2.3"
-	)}
-
-seq(Revolver.settings: _*)
+Seq(Revolver.settings: _*)
+lazy val bbbFSESLClient = (project in file(".")).settings(name := "bbb-fsesl-client", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
 //-----------
 // Packaging
@@ -42,7 +52,7 @@ crossPaths := false
 // This forbids including Scala related libraries into the dependency
 autoScalaLibrary := false
 
-publishTo := Some(Resolver.file("file",  new File(Path.userHome.absolutePath+"/.m2/repository")))
+publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath + "/.m2/repository")))
 
 //publishTo := {
 //  val nexus = "https://oss.sonatype.org/"
@@ -60,10 +70,10 @@ publishArtifact in Test := false
 
 // http://www.scala-sbt.org/release/docs/Artifacts.html
 // disable publishing the main API jar
-publishArtifact in (Compile, packageDoc) := false
+publishArtifact in(Compile, packageDoc) := false
 
 // disable publishing the main sources jar
-publishArtifact in (Compile, packageSrc) := false
+publishArtifact in(Compile, packageSrc) := false
 
 pomIncludeRepository := { _ => false }
 
@@ -72,14 +82,14 @@ pomExtra := (
     <url>git@github.com:bigbluebutton/bigbluebutton.git</url>
     <connection>scm:git:git@github.com:bigbluebutton/bigbluebutton.git</connection>
   </scm>
-  <developers>
-    <developer>
-      <id>ritzalam</id>
-      <name>Richard Alam</name>
-      <url>http://www.bigbluebutton.org</url>
-    </developer>
-  </developers>)
-  
+    <developers>
+      <developer>
+        <id>ritzalam</id>
+        <name>Richard Alam</name>
+        <url>http://www.bigbluebutton.org</url>
+      </developer>
+    </developers>)
+
 licenses := Seq("Apache License, Version 2.0" -> url("http://opensource.org/licenses/Apache-2.0"))
 
 homepage := Some(url("http://www.bigbluebutton.org"))
diff --git a/bbb-fsesl-client/deploy.sh b/bbb-fsesl-client/deploy.sh
index a5f14b0d75d69db2a5f3bfb38226a0f1f643c13d..fdfce32665453b90bcea6d522bcaf673fb56f93b 100644
--- a/bbb-fsesl-client/deploy.sh
+++ b/bbb-fsesl-client/deploy.sh
@@ -1,2 +1 @@
-sbt clean
-sbt publish publishLocal
+sbt clean publish publishLocal
diff --git a/bbb-fsesl-client/project/Build.scala b/bbb-fsesl-client/project/Build.scala
deleted file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/bbb-fsesl-client/project/Dependencies.scala b/bbb-fsesl-client/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9da6506153827201f161ef66183863558c91b4f2
--- /dev/null
+++ b/bbb-fsesl-client/project/Dependencies.scala
@@ -0,0 +1,40 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+
+    // Libraries
+    val netty = "3.2.10.Final"
+    val logback = "1.2.3"
+
+    // Test
+    val junit = "4.12"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaCompiler = "org.scala-lang" % "scala-compiler" % Versions.scala
+
+    val netty = "org.jboss.netty" % "netty" % Versions.netty
+    val logback = "ch.qos.logback" % "logback-classic" % Versions.logback
+  }
+
+  object Test {
+    val junit = "junit" % "junit" % Versions.junit % "test"
+  }
+
+  val testing = Seq(
+    Test.junit)
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaCompiler,
+    Compile.netty,
+    Compile.logback) ++ testing
+}
diff --git a/bbb-fsesl-client/project/build.properties b/bbb-fsesl-client/project/build.properties
index a6e117b61042ee81c62ba3a0fc5210d9502944df..2e6e3d24608ee15e892ed3b16d84224f7667e808 100755
--- a/bbb-fsesl-client/project/build.properties
+++ b/bbb-fsesl-client/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=1.2.6
\ No newline at end of file
diff --git a/bbb-fsesl-client/project/plugins.sbt b/bbb-fsesl-client/project/plugins.sbt
index 5ab7b095f69a2b3d8a3bf5350fa7e7e1a64f8f2f..3559bf68d62ef19f25fa810533bbe596eb022d02 100755
--- a/bbb-fsesl-client/project/plugins.sbt
+++ b/bbb-fsesl-client/project/plugins.sbt
@@ -2,8 +2,8 @@ addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
+addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1")
 
-addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
+addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.8")
 
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
diff --git a/bbb-fsesl-client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java b/bbb-fsesl-client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java
index e3577e52fd6de92f692f7531c168fecbaf4ab252..fb15b27bd2cd7c0b16219291cc0451d43e58ed01 100644
--- a/bbb-fsesl-client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java
+++ b/bbb-fsesl-client/src/test/java/org/freeswitch/esl/client/inbound/ClientTest.java
@@ -17,12 +17,11 @@ package org.freeswitch.esl.client.inbound;
 
 import java.util.Map.Entry;
 
-import org.freeswitch.esl.client.IEslEventListener;
-import org.freeswitch.esl.client.inbound.Client;
-import org.freeswitch.esl.client.inbound.InboundConnectionFailure;
+import org.freeswitch.esl.client.example.EslEventListener;
 import org.freeswitch.esl.client.transport.event.EslEvent;
-import org.freeswitch.esl.client.transport.message.EslMessage;
 import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.jboss.netty.channel.ExceptionEvent;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,7 +39,7 @@ public class ClientTest
     {
         Client client = new Client();
      
-        client.addEventListener( new IEslEventListener()
+        client.addEventListener( new EslEventListener()
         {
             public void eventReceived( EslEvent event )
             {
diff --git a/bbb-screenshare/app/build.sbt b/bbb-screenshare/app/build.sbt
index dc47de3dedc1ee69a30ebd348a40ddcf5f1ebd44..a49598ac7d645e2454021d987f743758ef29001e 100755
--- a/bbb-screenshare/app/build.sbt
+++ b/bbb-screenshare/app/build.sbt
@@ -1,28 +1,30 @@
+import org.bigbluebutton.build._
 
 //enablePlugins(JavaServerAppPackaging)
 enablePlugins(JettyPlugin)
 
-name := "bbb-screenshare-akka"
-
-organization := "org.bigbluebutton"
-
-version := "0.0.2"
-
-scalaVersion  := "2.12.6"
-
-scalacOptions ++= Seq(
-  "-unchecked",
-  "-deprecation",
-  "-Xlint",
-  "-Ywarn-dead-code",
-  "-language:_",
-  "-target:jvm-1.8",
-  "-encoding", "UTF-8"
+version := "0.0.3"
+
+val compileSettings = Seq(
+  organization := "org.bigbluebutton",
+
+  scalacOptions ++= List(
+    "-unchecked",
+    "-deprecation",
+    "-Xlint",
+    "-Ywarn-dead-code",
+    "-language:_",
+    "-target:jvm-1.8",
+    "-encoding", "UTF-8"
+  ),
+  javacOptions ++= List(
+    "-Xlint:unchecked",
+    "-Xlint:deprecation"
+  )
 )
 
 resolvers ++= Seq(
   "spray repo" at "http://repo.spray.io/",
-  "rediscala" at "http://dl.bintray.com/etaty/maven",
   "blindside-repos" at "http://blindside.googlecode.com/svn/repository/"
 )
 
@@ -39,45 +41,8 @@ testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "html", "console",
 
 testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scalatest-reports")
 
-val akkaVersion  = "2.5.14"
-val scalaTestV  = "2.2.6"
-
-libraryDependencies ++= {
-    val springVersion = "4.3.12.RELEASE"
-  Seq(
-    "com.typesafe.akka"        %%  "akka-actor"        % akkaVersion,
-    "com.typesafe.akka"        %%  "akka-testkit"      % akkaVersion    % "test",
-    "com.typesafe.akka"        %%  "akka-slf4j"        % akkaVersion,
-    "com.typesafe"              %  "config"            % "1.3.0",
-    "ch.qos.logback"            %  "logback-classic"   % "1.2.3" % "runtime",
-    "commons-codec"             %  "commons-codec"     % "1.11",
-    "redis.clients"             %  "jedis"             % "2.9.0",
-    "org.apache.commons"        %  "commons-pool2"     % "2.6.0",
-    "org.red5"                  %  "red5-server"       % "1.0.10-M5",
-    "com.google.code.gson"      %  "gson"              % "2.8.5",
-    "org.springframework"       %  "spring-web"        % springVersion,
-    "org.springframework"       %  "spring-beans"      % springVersion,
-    "org.springframework"       %  "spring-context"    % springVersion,
-    "org.springframework"       %  "spring-core"       % springVersion,
-    "org.springframework"       %  "spring-webmvc"     % springVersion,
-    "org.springframework"       %  "spring-aop"        % springVersion,
-    "javax.servlet"             %  "servlet-api"       % "2.5"
-  )}
-
-// https://mvnrepository.com/artifact/org.scala-lang/scala-library
-libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value
-libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
-
-libraryDependencies += "org.bigbluebutton" % "bbb-common-message_2.12" % "0.0.19-SNAPSHOT"
-// https://mvnrepository.com/artifact/com.github.etaty/rediscala_2.12
-libraryDependencies += "com.github.etaty" % "rediscala_2.12" % "1.8.0"
-// https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-scala_2.12
-libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala_2.12" % "2.9.6"
-
-//seq(Revolver.settings: _*)
-//
-//scalariformSettings
-
+Seq(Revolver.settings: _*)
+lazy val bbbScreenshareAkka = (project in file(".")).settings(name := "bbb-screenshare-akka", libraryDependencies ++= Dependencies.runtime).settings(compileSettings)
 
 //-----------
 // Packaging
diff --git a/bbb-screenshare/app/deploy.sh b/bbb-screenshare/app/deploy.sh
index a21a310dbb12dcf7258fdfd49cb43ee187c31545..69d99a0f08fa0b716c734b4a525efc203e0c6922 100755
--- a/bbb-screenshare/app/deploy.sh
+++ b/bbb-screenshare/app/deploy.sh
@@ -1,52 +1,45 @@
 #!/bin/bash
 # deploying 'screenshare' to /usr/share/red5/webapps
 
-sbt clean
-sbt compile
-sbt package
+sbt clean compile package
+
 if [[ -d /usr/share/red5/webapps/screenshare ]]; then
     sudo rm -r /usr/share/red5/webapps/screenshare
 fi
 sudo cp -r target/webapp/ /usr/share/red5/webapps/screenshare
 
-
 sudo rm -rf /usr/share/red5/webapps/screenshare/WEB-INF/lib/*
-sudo cp ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/bbb-screenshare-akka_2.12-0.0.2.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/scala-library-* \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/scala-reflect-* \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/jackson-* \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/paranamer-2.8.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/akka-* \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/config-1.3.3.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/gson-2.8.5.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/jedis-2.9.0.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/commons-pool2-2.6.0.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/spring-webmvc-4.3.12.RELEASE.jar  \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/rediscala_2.12-1.8.0.jar  \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/bbb-common-message_2.12-0.0.19-SNAPSHOT.jar \
+sudo cp target/webapp/WEB-INF/lib/bbb-screenshare-akka_2.12-0.0.3.jar \
+ target/webapp/WEB-INF/lib/scala-library.jar \
+ target/webapp/WEB-INF/lib/scala-reflect.jar \
+ target/webapp/WEB-INF/lib/jackson-* \
+ target/webapp/WEB-INF/lib/paranamer-2.8.jar \
+ target/webapp/WEB-INF/lib/akka-* \
+ target/webapp/WEB-INF/lib/config-1.3.3.jar \
+ target/webapp/WEB-INF/lib/gson-2.8.5.jar \
+ target/webapp/WEB-INF/lib/commons-pool2-2.6.0.jar \
+ target/webapp/WEB-INF/lib/spring-webmvc-4.3.12.RELEASE.jar  \
+  target/webapp/WEB-INF/lib/bbb-common-message_2.12-0.0.20-SNAPSHOT.jar \
+ target/webapp/WEB-INF/lib/lettuce-core-5.1.3.RELEASE.jar \
+ target/webapp/WEB-INF/lib/netty-* \
+ target/webapp/WEB-INF/lib/reactor-core-3.2.3.RELEASE.jar \
+ target/webapp/WEB-INF/lib/reactive-streams-1.0.2.jar \
   /usr/share/red5/webapps/screenshare/WEB-INF/lib/
 
-
 #sudo mkdir /usr/share/red5/webapps/screenshare/WEB-INF/classes
 #cd /usr/share/red5/webapps/screenshare/WEB-INF/classes/
-#sudo jar -xf ../lib/bbb-screenshare-akka_2.12-0.0.2.jar
-#sudo rm /usr/share/red5/webapps/screenshare/WEB-INF/lib/bbb-screenshare-akka_2.12-0.0.2.jar
+#sudo jar -xf .lib/bbb-screenshare-akka_2.12-0.0.3.jar
+#sudo rm /usr/share/red5/webapps/screenshare/WEB-INF/lib/bbb-screenshare-akka_2.12-0.0.3.jar
 
-cd /usr/share/red5/webapps/screenshare
-sudo mkdir lib
-cd lib
-sudo cp -r ~/dev/bigbluebutton/bbb-screenshare/app/jws/lib/* .
-cd ..
-sudo cp ~/dev/bigbluebutton/bbb-screenshare/app/jws/screenshare.jnlp .
-sudo cp ~/dev/bigbluebutton/bbb-screenshare/app/jws/screenshare.jnlp.h264 .
+sudo mkdir -p /usr/share/red5/webapps/screenshare/lib
+sudo cp -r jws/lib/* /usr/share/red5/webapps/screenshare/lib
+sudo cp jws/screenshare.jnlp /usr/share/red5/webapps/screenshare
+sudo cp jws/screenshare.jnlp.h264 /usr/share/red5/webapps/screenshare
 
 sudo chmod -R 777 /usr/share/red5/webapps/screenshare
 sudo chown -R red5:red5 /usr/share/red5/webapps/screenshare
 
-# TODO change the owner username to 'firstuser'
-
 # // Dev only
 #sudo service red5 restart
 #sudo service tomcat7 restart
 #sudo service bbb-apps-akka restart
-
diff --git a/bbb-screenshare/app/project/Dependencies.scala b/bbb-screenshare/app/project/Dependencies.scala
new file mode 100644
index 0000000000000000000000000000000000000000..447f11e573748718d87aa46a0e05c95e78e7b0a1
--- /dev/null
+++ b/bbb-screenshare/app/project/Dependencies.scala
@@ -0,0 +1,105 @@
+package org.bigbluebutton.build
+
+import sbt._
+import Keys._
+
+object Dependencies {
+
+  object Versions {
+    // Scala
+    val scala = "2.12.7"
+    val junitInterface = "0.11"
+    val scalactic = "3.0.3"
+
+    // Libraries
+    val akkaVersion = "2.5.17"
+    val gson = "2.8.5"
+    val jackson = "2.9.7"
+    val logback = "1.2.3"
+    val springVersion = "4.3.12.RELEASE"
+    val red5 = "1.0.10-M5"
+    val servlet = "2.5"
+    val ffmpeg = "4.0.2-1.4.3"
+    val openCv = "1.4.3"
+
+    // Apache Commons
+    val lang = "3.7"
+    val codec = "1.11"
+    val pool2 = "2.6.0"
+
+    // Redis
+    val lettuce = "5.1.3.RELEASE"
+
+    // BigBlueButton
+    val bbbCommons = "0.0.20-SNAPSHOT"
+
+    // Test
+    val scalaTest = "3.0.5"
+    val akkaTestKit = "2.5.18"
+  }
+
+  object Compile {
+    val scalaLibrary = "org.scala-lang" % "scala-library" % Versions.scala
+    val scalaReflect = "org.scala-lang" % "scala-reflect" % Versions.scala
+
+    val akkaActor = "com.typesafe.akka" % "akka-actor_2.12" % Versions.akkaVersion
+    val akkaSl4fj = "com.typesafe.akka" % "akka-slf4j_2.12" % Versions.akkaVersion
+
+    val googleGson = "com.google.code.gson" % "gson" % Versions.gson
+    val jacksonModule = "com.fasterxml.jackson.module" %% "jackson-module-scala" % Versions.jackson
+    val logback = "ch.qos.logback" % "logback-classic" % Versions.logback % "runtime"
+    val red5Server = "org.red5" % "red5-server" % Versions.red5
+    val javaServlet = "javax.servlet" % "servlet-api" % Versions.servlet
+    val ffmpeg = "org.bytedeco.javacpp-presets" % "ffmpeg" % Versions.ffmpeg
+    val openCv = "org.bytedeco" % "javacv" % Versions.openCv
+
+    val springWeb = "org.springframework" % "spring-web" % Versions.springVersion
+    val springBeans = "org.springframework" % "spring-beans" % Versions.springVersion
+    val springContext = "org.springframework" % "spring-context" % Versions.springVersion
+    val springCore = "org.springframework" % "spring-core" % Versions.springVersion
+    val springWebmvc = "org.springframework" % "spring-webmvc" % Versions.springVersion
+    val springAop = "org.springframework" % "spring-aop" % Versions.springVersion
+
+    val commonsCodec = "commons-codec" % "commons-codec" % Versions.codec
+    val apacheLang = "org.apache.commons" % "commons-lang3" % Versions.lang
+    val apachePool2 = "org.apache.commons" % "commons-pool2" % Versions.pool2
+
+    val lettuceCore = "io.lettuce" % "lettuce-core" % Versions.lettuce
+
+    val bbbCommons = "org.bigbluebutton" % "bbb-common-message_2.12" % Versions.bbbCommons
+  }
+
+  object Test {
+    val scalaTest = "org.scalatest" %% "scalatest" % Versions.scalaTest % "test"
+    val scalactic = "org.scalactic" % "scalactic_2.12" % Versions.scalactic % "test"
+    val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % Versions.akkaTestKit % "test"
+  }
+
+  val testing = Seq(
+    Test.scalaTest,
+    Test.scalactic,
+    Test.akkaTestKit)
+
+  val runtime = Seq(
+    Compile.scalaLibrary,
+    Compile.scalaReflect,
+    Compile.akkaActor,
+    Compile.akkaSl4fj,
+    Compile.googleGson,
+    Compile.jacksonModule,
+    Compile.red5Server,
+    Compile.javaServlet,
+    Compile.ffmpeg,
+    Compile.openCv,
+    Compile.logback,
+    Compile.springWeb,
+    Compile.springBeans,
+    Compile.springContext,
+    Compile.springWebmvc,
+    Compile.springAop,
+    Compile.commonsCodec,
+    Compile.apacheLang,
+    Compile.apachePool2,
+    Compile.lettuceCore,
+    Compile.bbbCommons) ++ testing
+}
diff --git a/bbb-screenshare/app/project/build.properties b/bbb-screenshare/app/project/build.properties
new file mode 100644
index 0000000000000000000000000000000000000000..7c58a83abffb36afce7051243bff3a50e3fa3dab
--- /dev/null
+++ b/bbb-screenshare/app/project/build.properties
@@ -0,0 +1 @@
+sbt.version=1.2.6
diff --git a/bbb-screenshare/app/project/plugins.sbt b/bbb-screenshare/app/project/plugins.sbt
index 1c5c911f1db806157b151442a8ed6230cbd9afe9..0a2cbd1dd31631fd8a7a856591f2deeaf85a7840 100644
--- a/bbb-screenshare/app/project/plugins.sbt
+++ b/bbb-screenshare/app/project/plugins.sbt
@@ -1,15 +1,13 @@
 addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
 
-addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
-
 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
 
-addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.6")
-
-addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.1.0")
+addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
 
-//addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.7.9")
+addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.12")
 
-addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.7")
+addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "0.2.8")
 
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
+
+addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.0.2")
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/ScreenshareStreamListener.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/ScreenshareStreamListener.java
index 1e90ff0111d506485d1bf5cf12daa99acbbcf73a..7cbecf986d010a8f1a957462773b2ea41640f055 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/ScreenshareStreamListener.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/ScreenshareStreamListener.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.mina.core.buffer.IoBuffer;
+import org.bigbluebutton.common2.redis.RedisStorageService;
 import org.red5.server.api.IConnection;
 import org.red5.server.api.Red5;
 import org.red5.server.api.stream.IBroadcastStream;
@@ -46,11 +47,11 @@ import org.red5.server.net.rtmp.event.VideoData;
  *
  */
 public class ScreenshareStreamListener implements IStreamListener {
-	private EventRecordingService recordingService;
+	private RedisStorageService recordingService;
 	private volatile boolean firstPacketReceived = false;
 	private String recordingDir;
 	
-	public ScreenshareStreamListener(EventRecordingService s, String recordingDir) {
+	public ScreenshareStreamListener(RedisStorageService s, String recordingDir) {
 	  this.recordingService = s;
 	  this.recordingDir = recordingDir;
 	}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java
index 41468e7ed845331d4706df0ab30a711a6d70f35a..bf91a9770f607ffc91bb3974ec24d4ac6bf37cb1 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java
@@ -17,24 +17,24 @@
  */
 package org.bigbluebutton.app.screenshare;
 
+import java.text.SimpleDateFormat;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.mina.core.buffer.IoBuffer;
+import org.bigbluebutton.common2.redis.RedisStorageService;
+import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.api.scheduling.IScheduledJob;
 import org.red5.server.api.scheduling.ISchedulingService;
-import org.red5.server.api.scope.IScope;
 import org.red5.server.api.stream.IBroadcastStream;
 import org.red5.server.api.stream.IStreamListener;
 import org.red5.server.api.stream.IStreamPacket;
 import org.red5.server.net.rtmp.event.VideoData;
 import org.red5.server.scheduling.QuartzSchedulingService;
 import org.slf4j.Logger;
-import org.red5.logging.Red5LoggerFactory;
 
 import com.google.gson.Gson;
-import java.text.SimpleDateFormat;
 
 /**
  * Class to listen for the first video packet of the webcam.
@@ -54,7 +54,7 @@ import java.text.SimpleDateFormat;
 public class VideoStreamListener implements IStreamListener {
   private static final Logger log = Red5LoggerFactory.getLogger(VideoStreamListener.class, "screenshare");
 
-  private EventRecordingService recordingService;
+  private RedisStorageService redisStorageService;
   private volatile boolean firstPacketReceived = false;
 
   // Maximum time between video packets
@@ -96,14 +96,14 @@ public class VideoStreamListener implements IStreamListener {
   public VideoStreamListener(String meetingId, String streamId, Boolean record,
                              String recordingDir, int packetTimeout,
                              QuartzSchedulingService scheduler,
-                             EventRecordingService recordingService) {
+                             RedisStorageService recordingService) {
     this.meetingId = meetingId;
     this.streamId = streamId;
     this.record = record;
     this.videoTimeout = packetTimeout;
     this.recordingDir = recordingDir;
     this.scheduler = scheduler;
-    this.recordingService = recordingService;
+    this.redisStorageService = recordingService;
 
     // start the worker to monitor if we are still receiving video packets
     timeoutJobName = scheduler.addScheduledJob(videoTimeout, new TimeoutJob());
@@ -166,7 +166,7 @@ public class VideoStreamListener implements IStreamListener {
 					event.put(DATE, sdf.format(recordingStartTime));
 					event.put("eventName", "DeskshareStartedEvent");
 
-					recordingService.record(meetingId, event);
+					redisStorageService.record(meetingId, event);
 
 
 					Gson gson = new Gson();
@@ -233,7 +233,7 @@ public class VideoStreamListener implements IStreamListener {
 			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
 			event.put(DATE, sdf.format(now));
 			event.put("eventName", "DeskshareStoppedEvent");
-      recordingService.record(meetingId, event);
+      redisStorageService.record(meetingId, event);
 
 			Gson gson = new Gson();
 			String logStr = gson.toJson(event);
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java
deleted file mode 100755
index 182ab1dac605fa0b6cdc2e7216ab476de0afecdc..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bigbluebutton.app.screenshare.messaging.redis;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.Protocol;
-
-public class MessageSender {
-    private static Logger log = Red5LoggerFactory.getLogger(MessageSender.class, "bigbluebutton");
-
-    private volatile boolean sendMessage = false;
-    private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
-    private final Executor runExec = Executors.newSingleThreadExecutor();
-    private BlockingQueue<MessageToSend> messages = new LinkedBlockingQueue<MessageToSend>();
-
-    private JedisPool redisPool;
-    private String host;
-    private int port;
-
-    public void stop() {
-        sendMessage = false;
-        redisPool.destroy();
-    }
-
-    public void start() {
-        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
-        config.setMaxTotal(32);
-        config.setMaxIdle(8);
-        config.setMinIdle(1);
-        config.setTestOnBorrow(true);
-        config.setTestOnReturn(true);
-        config.setTestWhileIdle(true);
-        config.setNumTestsPerEvictionRun(12);
-        config.setMaxWaitMillis(5000);
-        config.setTimeBetweenEvictionRunsMillis(60000);
-        config.setBlockWhenExhausted(true);
-
-        // Set the name of this client to be able to distinguish when doing
-        // CLIENT LIST on redis-cli
-        redisPool = new JedisPool(config, host, port, Protocol.DEFAULT_TIMEOUT, null,
-                Protocol.DEFAULT_DATABASE, "BbbRed5AppsPub");
-
-        log.info("Redis message publisher starting!");
-        try {
-            sendMessage = true;
-
-            Runnable messageSender = new Runnable() {
-                public void run() {
-                    while (sendMessage) {
-                        try {
-                            MessageToSend msg = messages.take();
-                            publish(msg.getChannel(), msg.getMessage());
-                        } catch (InterruptedException e) {
-                            log.warn("Failed to get message from queue.");
-                        }
-                    }
-                }
-            };
-            msgSenderExec.execute(messageSender);
-        } catch (Exception e) {
-            log.error("Error subscribing to channels: " + e.getMessage());
-        }
-    }
-
-    public void send(String channel, String message) {
-        MessageToSend msg = new MessageToSend(channel, message);
-        messages.add(msg);
-    }
-
-    private void publish(final String channel, final String message) {
-        Runnable task = new Runnable() {
-            public void run() {
-                Jedis jedis = redisPool.getResource();
-                try {
-                    jedis.publish(channel, message);
-                } catch(Exception e){
-                    log.warn("Cannot publish the message to redis", e);
-                } finally {
-                    jedis.close();
-                }
-            }
-        };
-
-        runExec.execute(task);
-    }
-
-    public void setHost(String host){
-        this.host = host;
-    }
-
-    public void setPort(int port) {
-        this.port = port;
-    }
-}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java
index 432f4049a08a30376e42869588daf798d68a6749..142b9a2a50c8f7d2bb93572521a0b0e61ab6cb69 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java
@@ -24,24 +24,22 @@ import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.bigbluebutton.app.screenshare.IScreenShareApplication;
+import org.bigbluebutton.app.screenshare.MeetingManager;
+import org.bigbluebutton.app.screenshare.VideoStream;
+import org.bigbluebutton.app.screenshare.VideoStreamListener;
+import org.bigbluebutton.common2.redis.RedisStorageService;
 import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.adapter.MultiThreadedApplicationAdapter;
 import org.red5.server.api.IConnection;
 import org.red5.server.api.Red5;
 import org.red5.server.api.scope.IScope;
 import org.red5.server.api.stream.IBroadcastStream;
-import org.red5.server.api.stream.IServerStream;
-import org.red5.server.api.stream.IStreamListener;
+import org.red5.server.scheduling.QuartzSchedulingService;
 import org.red5.server.stream.ClientBroadcastStream;
 import org.slf4j.Logger;
-import org.red5.server.scheduling.QuartzSchedulingService;
+
 import com.google.gson.Gson;
-import org.bigbluebutton.app.screenshare.MeetingManager;
-import org.bigbluebutton.app.screenshare.VideoStreamListener;
-import org.bigbluebutton.app.screenshare.VideoStream;
-import org.bigbluebutton.app.screenshare.EventRecordingService;
-import org.bigbluebutton.app.screenshare.IScreenShareApplication;
-import org.bigbluebutton.app.screenshare.ScreenshareStreamListener;
 
 public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
   private static Logger log = Red5LoggerFactory.getLogger(Red5AppAdapter.class, "screenshare");
@@ -49,7 +47,7 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
   // Scheduler
   private QuartzSchedulingService scheduler;
 
-  private EventRecordingService recordingService;
+  private RedisStorageService redisStorageService;
   private IScreenShareApplication app;
   private String streamBaseUrl;
   private ConnectionInvokerService sender;
@@ -196,7 +194,7 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
 				log.info(logStr2);
 
 				VideoStreamListener listener = new VideoStreamListener(meetingId, streamId,
-								recordVideoStream, recordingDirectory, packetTimeout, scheduler, recordingService);
+								recordVideoStream, recordingDirectory, packetTimeout, scheduler, redisStorageService);
 				ClientBroadcastStream cstream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), stream.getPublishedName());
 				stream.addStreamListener(listener);
 				VideoStream vstream = new VideoStream(stream, listener, cstream);
@@ -255,8 +253,8 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
     this.meetingManager = meetingManager;
   }
 
-  public void setEventRecordingService(EventRecordingService s) {
-    recordingService = s;
+  public void setRedisStorageService(RedisStorageService s) {
+    redisStorageService = s;
   }
 
   public void setStreamBaseUrl(String baseUrl) {
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java
index da895535568acdabfc6d19509c72c25b3318e650..1e459fafa28e53ad935c41966c408f2adb361f0a 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java
@@ -3,19 +3,18 @@ package org.bigbluebutton.app.screenshare.red5;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import org.bigbluebutton.app.screenshare.messaging.redis.MessageSender;
+
 import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.api.IConnection;
 import org.red5.server.api.Red5;
 import org.slf4j.Logger;
+
 import com.google.gson.Gson;
 
 public class Red5AppService {
   private static Logger log = Red5LoggerFactory.getLogger(Red5AppService.class, "screenshare");
   
   private Red5AppHandler handler;
-  private MessageSender red5RedisSender;
 
   /**
    * Called from the client to pass us the userId.
@@ -180,15 +179,7 @@ public class Red5AppService {
     handler.screenShareClientPongMessage(meetingId, userId, streamId, timestamp.longValue());
   }
 
-  private Long genTimestamp() {
-    return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
-  }
-
   public void setAppHandler(Red5AppHandler handler) {
     this.handler = handler;
   }
-
-  public void setRed5RedisSender(MessageSender red5RedisSender) {
-      this.red5RedisSender = red5RedisSender;
-  }
 }
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/server/recorder/EventRecorder.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/server/recorder/EventRecorder.java
deleted file mode 100755
index ec4452c66ea6600f878cfd91355bd3283aed6aa2..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/server/recorder/EventRecorder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
-package org.bigbluebutton.app.screenshare.server.recorder;
-
-import java.util.concurrent.TimeUnit;
-
-import org.bigbluebutton.app.screenshare.server.recorder.event.AbstractDeskshareRecordEvent;
-import org.bigbluebutton.app.screenshare.server.recorder.event.RecordEvent;
-import org.bigbluebutton.app.screenshare.server.recorder.event.RecordStartedEvent;
-import org.bigbluebutton.app.screenshare.server.recorder.event.RecordStoppedEvent;
-
-import redis.clients.jedis.Jedis;
-
-public class EventRecorder implements RecordStatusListener {
-	private static final String COLON=":";
-	private String host;
-	private int port;
-
-	public EventRecorder(String host, int port){
-		this.host = host;
-		this.port = port;		
-	}
-	
-  private Long genTimestamp() {
-  	return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
-  }
-  
-	private void record(String session, RecordEvent message) {
-		Jedis jedis = new Jedis(host, port);
-		Long msgid = jedis.incr("global:nextRecordedMsgId");
-		jedis.hmset("recording" + COLON + session + COLON + msgid, message.toMap());
-		jedis.rpush("meeting" + COLON + session + COLON + "recordings", msgid.toString());						
-	}
-	
-	@Override
-	public void notify(RecordEvent event) {
-		if ((event instanceof RecordStoppedEvent) || (event instanceof RecordStartedEvent)) {
-			event.setTimestamp(genTimestamp());
-			event.setMeetingId(((AbstractDeskshareRecordEvent)event).getSession());
-			record(((AbstractDeskshareRecordEvent)event).getSession(), event);
-		}
-	}
-}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/store/redis/RedisDataStore.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/store/redis/RedisDataStore.java
deleted file mode 100755
index e1900231febfe63631debd14a2c6a61702f4e220..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/store/redis/RedisDataStore.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bigbluebutton.app.screenshare.store.redis;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-
-public class RedisDataStore {
-  private static Logger log = Red5LoggerFactory.getLogger(RedisDataStore.class, "screenshare");
-
-  private JedisPool redisPool;
-  private volatile boolean sendMessage = false;
-  private int maxThreshold = 1024;
-  private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
-  private BlockingQueue<IScreenShareData> dataToStore = new LinkedBlockingQueue<IScreenShareData>();
-  private final Executor runExec = Executors.newSingleThreadExecutor();
-
-  public void stop() {
-    sendMessage = false;
-  }
-
-  public void start() {   
-    try {
-      sendMessage = true;
-
-      Runnable messageSender = new Runnable() {
-        public void run() {
-          while (sendMessage) {
-            try {
-              IScreenShareData data = dataToStore.take();
-              storeData(data);
-            } catch (InterruptedException e) {
-              log.warn("Failed to get data from queue.");
-            }                           
-          }
-        }
-      };
-      msgSenderExec.execute(messageSender);
-    } catch (Exception e) {
-      log.error("Error storing data into redis: " + e.getMessage());
-    }           
-  }
-
-  public void store(IScreenShareData data) {
-    if (dataToStore.size() > maxThreshold) {
-      log.warn("Queued number of data [{}] is greater than threshold [{}]", dataToStore.size(), maxThreshold);
-    }
-    dataToStore.add(data);
-  }
-
-  private void storeData(IScreenShareData data) {
-    Runnable task = new Runnable() {
-      public void run() {
-        Jedis jedis = redisPool.getResource();
-        try {
-          //              jedis.publish(channel, message);
-        } catch(Exception e){
-          log.warn("Cannot publish the message to redis", e);
-        } finally {
-          redisPool.returnResource(jedis);
-        }           
-      }
-    };
-
-    runExec.execute(task);
-  }
-
-  public void setRedisPool(JedisPool redisPool){
-    this.redisPool = redisPool;
-  }
-
-  public void setMaxThreshold(int threshold) {
-    maxThreshold = threshold;
-  }
-}
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala
index cb3082f1a6e119ab56337eab61cfdacc2035430a..d1c42cdd8c86e4d22ef02f7add2d8e3f287a8b0b 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala
@@ -26,10 +26,11 @@ import org.bigbluebutton.app.screenshare.server.sessions.ScreenshareManager
 import org.bigbluebutton.app.screenshare.server.sessions.messages._
 import org.bigbluebutton.app.screenshare.server.util.LogHelper
 import akka.actor.ActorSystem
-import org.bigbluebutton.app.screenshare.redis.{ AppsRedisSubscriberActor, IncomingJsonMessageBus, ReceivedJsonMsgHandlerActor }
+import org.bigbluebutton.app.screenshare.redis.{ ScreenshareRedisSubscriberActor, ReceivedJsonMsgHandlerActor }
 
 import scala.concurrent.{ Await, Future, TimeoutException }
 import scala.concurrent.duration._
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
 
 class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
   val streamBaseUrl: String) extends IScreenShareApplication
@@ -46,7 +47,7 @@ class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
   //logger.debug("*********** meetingManagerChannel = " + meetingManagerChannel)
 
   val incomingJsonMessageBus = new IncomingJsonMessageBus
-  val redisSubscriberActor = system.actorOf(AppsRedisSubscriberActor.props(incomingJsonMessageBus), "redis-subscriber")
+  val redisSubscriberActor = system.actorOf(ScreenshareRedisSubscriberActor.props(system, incomingJsonMessageBus), "redis-subscriber")
 
   val screenShareManager = system.actorOf(ScreenshareManager.props(system, bus), "screenshare-manager")
 
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/SystemConfiguration.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/SystemConfiguration.scala
index c25b684048db28d44b04cc90e5eef302c56ccb50..a838726e128301e5f91b955e81e123f832ac8523 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/SystemConfiguration.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/SystemConfiguration.scala
@@ -2,18 +2,11 @@ package org.bigbluebutton.app.screenshare
 
 import scala.util.Try
 import com.typesafe.config.ConfigFactory
+import org.bigbluebutton.common2.redis.RedisConfiguration
 
-trait SystemConfiguration {
-
-  //val config = ConfigFactory.load("screenshare-app")
-  val config = ConfigFactory.load()
-
-  lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
-  lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
-  lazy val redisPassword = Try(config.getString("redis.password")).getOrElse("")
+trait SystemConfiguration extends RedisConfiguration {
 
   lazy val meetingManagerChannel = Try(config.getString("eventBus.meetingManagerChannel")).getOrElse("NOT FROM APP CONF")
 
   lazy val toScreenshareAppsJsonChannel = Try(config.getString("eventBus.toAkkaAppsChannel")).getOrElse("to-screenshare-apps-json-channel")
-  lazy val fromAkkaAppsRedisChannel = Try(config.getString("redis.fromAkkaAppsRedisChannel")).getOrElse("from-akka-apps-redis-channel")
 }
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/AppsRedisSubscriberActor.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/AppsRedisSubscriberActor.scala
deleted file mode 100755
index 36bbc477fc0d0201f1a875f03bdb1dbad7599324..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/AppsRedisSubscriberActor.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bigbluebutton.app.screenshare.redis
-
-import java.io.{ PrintWriter, StringWriter }
-import java.net.InetSocketAddress
-
-import akka.actor.{ OneForOneStrategy, Props }
-import akka.actor.SupervisorStrategy.Resume
-import org.bigbluebutton.app.screenshare.SystemConfiguration
-import redis.actors.RedisSubscriberActor
-import redis.api.servers.ClientSetname
-import redis.actors.RedisSubscriberActor
-import redis.api.pubsub.{ Message, PMessage }
-import scala.concurrent.duration._
-
-object AppsRedisSubscriberActor extends SystemConfiguration {
-
-  val channels = Seq(fromAkkaAppsRedisChannel)
-  val patterns = Seq("bigbluebutton:to-bbb-apps:*", "bigbluebutton:from-voice-conf:*")
-
-  def props(jsonMsgBus: IncomingJsonMessageBus): Props =
-    Props(classOf[AppsRedisSubscriberActor], jsonMsgBus,
-      redisHost, redisPort,
-      channels, patterns).withDispatcher("akka.rediscala-subscriber-worker-dispatcher")
-}
-
-class AppsRedisSubscriberActor(jsonMsgBus: IncomingJsonMessageBus, redisHost: String,
-  redisPort: Int,
-  channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
-  extends RedisSubscriberActor(
-    new InetSocketAddress(redisHost, redisPort),
-    channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") }) with SystemConfiguration {
-
-  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
-    case e: Exception => {
-      val sw: StringWriter = new StringWriter()
-      sw.write("An exception has been thrown on AppsRedisSubscriberActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
-      e.printStackTrace(new PrintWriter(sw))
-      log.error(sw.toString())
-      Resume
-    }
-  }
-
-  // Set the name of this client to be able to distinguish when doing
-  // CLIENT LIST on redis-cli
-  write(ClientSetname("BbbScreenshareAkkaSub").encodedRequest)
-
-  def onMessage(message: Message) {
-    //log.error(s"SHOULD NOT BE RECEIVING: $message")
-    if (message.channel == fromAkkaAppsRedisChannel) {
-      val receivedJsonMessage = new ReceivedJsonMessage(message.channel, message.data.utf8String)
-      //log.debug(s"RECEIVED:\n [${receivedJsonMessage.channel}] \n ${receivedJsonMessage.data} \n")
-      jsonMsgBus.publish(IncomingJsonMessage(toScreenshareAppsJsonChannel, receivedJsonMessage))
-    }
-  }
-
-  def onPMessage(pmessage: PMessage) {
-    //log.debug(s"RECEIVED:\n ${pmessage.data.utf8String} \n")
-  }
-}
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/IncomingJsonMessageBus.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/IncomingJsonMessageBus.scala
deleted file mode 100755
index 532b120a86c332aaec568ed93dd0941bc21f5fcf..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/IncomingJsonMessageBus.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bigbluebutton.app.screenshare.redis
-
-import akka.actor.ActorRef
-import akka.event.{ EventBus, LookupClassification }
-
-case class ReceivedJsonMessage(channel: String, data: String)
-case class IncomingJsonMessage(val topic: String, val payload: ReceivedJsonMessage)
-
-class IncomingJsonMessageBus extends EventBus with LookupClassification {
-  type Event = IncomingJsonMessage
-  type Classifier = String
-  type Subscriber = ActorRef
-
-  // is used for extracting the classifier from the incoming events
-  override protected def classify(event: Event): Classifier = event.topic
-
-  // will be invoked for each event for all subscribers which registered themselves
-  // for the event’s classifier
-  override protected def publish(event: Event, subscriber: Subscriber): Unit = {
-    subscriber ! event.payload
-  }
-
-  // must define a full order over the subscribers, expressed as expected from
-  // `java.lang.Comparable.compare`
-  override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
-    a.compareTo(b)
-
-  // determines the initial size of the index data structure
-  // used internally (i.e. the expected number of different classifiers)
-  override protected def mapSize: Int = 128
-}
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ReceivedJsonMsgHandlerActor.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ReceivedJsonMsgHandlerActor.scala
index 36d638988c3a31b63c4149b6f53b8cd2b6db2af0..ca57f9d59956fbd81963126d41fb0903f7637b59 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ReceivedJsonMsgHandlerActor.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ReceivedJsonMsgHandlerActor.scala
@@ -5,7 +5,8 @@ import org.bigbluebutton.app.screenshare.server.sessions.messages.{ MeetingCreat
 import akka.actor.{ Actor, ActorLogging, ActorRef, Props }
 
 import scala.reflect.runtime.universe._
-import org.bigbluebutton.common2.msgs._
+import org.bigbluebutton.common2.msgs._
+import org.bigbluebutton.common2.bus.ReceivedJsonMessage
 
 object ReceivedJsonMsgHandlerActor {
   def props(screenshareManager: ActorRef): Props =
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ScreenshareRedisSubscriberActor.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ScreenshareRedisSubscriberActor.scala
new file mode 100755
index 0000000000000000000000000000000000000000..8c4875497e4d2065644e23aa1469ceca4a1d959d
--- /dev/null
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/redis/ScreenshareRedisSubscriberActor.scala
@@ -0,0 +1,32 @@
+package org.bigbluebutton.app.screenshare.redis
+
+import org.bigbluebutton.app.screenshare.SystemConfiguration
+import org.bigbluebutton.common2.bus.IncomingJsonMessageBus
+import org.bigbluebutton.common2.redis.RedisSubscriberProvider
+
+import akka.actor.ActorSystem
+import akka.actor.Props
+
+object ScreenshareRedisSubscriberActor extends SystemConfiguration {
+
+  val channels = Seq(fromAkkaAppsRedisChannel)
+  val patterns = Seq("bigbluebutton:to-bbb-apps:*", "bigbluebutton:from-voice-conf:*")
+
+  def props(system: ActorSystem, jsonMsgBus: IncomingJsonMessageBus): Props =
+    Props(
+      classOf[ScreenshareRedisSubscriberActor],
+      system, jsonMsgBus,
+      redisHost, redisPort,
+      channels, patterns).withDispatcher("akka.redis-subscriber-worker-dispatcher")
+}
+
+class ScreenshareRedisSubscriberActor(
+  system: ActorSystem,
+  jsonMsgBus: IncomingJsonMessageBus,
+  redisHost: String, redisPort: Int,
+  channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
+  extends RedisSubscriberProvider(system, "BbbScreenshareAkkaSub", channels, patterns, jsonMsgBus) with SystemConfiguration {
+
+  addListener(toScreenshareAppsJsonChannel)
+  subscribe()
+}
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/util/LogHelper.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/util/LogHelper.scala
index dbe83dc52d9a768277f146622f565f816d6b2033..2ed8ee87d1a79cd87144b8b0c09b2e4bc9d4c960 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/util/LogHelper.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/util/LogHelper.scala
@@ -1,6 +1,5 @@
 package org.bigbluebutton.app.screenshare.server.util
 
-import org.slf4j.Logger
 import org.red5.logging.Red5LoggerFactory
 
 /**
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-red5-redis-pubsub.xml b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-red5-redis-pubsub.xml
deleted file mode 100755
index d056fd28aa14a8c318a9a45c428f294edc6cadee..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-red5-redis-pubsub.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-
-Copyright (c) 2014 BigBlueButton Inc. and by respective authors (see below).
-
-This program is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free Software
-Foundation; either version 3.0 of the License, or (at your option) any later
-version.
-
-BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans
-			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-			http://www.springframework.org/schema/util
-			http://www.springframework.org/schema/util/spring-util-2.0.xsd
-			">
-
-    <bean id="red5RedisSender"
-          class="org.bigbluebutton.app.screenshare.messaging.redis.MessageSender"
-                    init-method="start" destroy-method="stop">
-      <property name="host" value="${redis.host}" />
-      <property name="port" value="${redis.port}" />
-    </bean>
-
-</beans>
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-pool.xml b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
similarity index 78%
rename from bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-pool.xml
rename to bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
index 5aa3cc5f9aefa4a4b8af09abc545e26a898800db..49057aa845d009416b86f9763d1602060c0ae688 100755
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-pool.xml
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
@@ -27,10 +27,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 			http://www.springframework.org/schema/util/spring-util-2.0.xsd
 			">
 
-<!--
-	<bean id="redisPool" class="redis.clients.jedis.JedisPool">
-		<constructor-arg index="0" value="${redis.host}"/>
-		<constructor-arg index="1" value="${redis.port}"/>
+	<bean id="redisStorageService"
+		class="org.bigbluebutton.common2.redis.RedisStorageService"
+		init-method="start" destroy-method="stop">
+		<property name="host" value="${redis.host}" />
+		<property name="port" value="${redis.port}" />
+		<property name="password" value="${redis.password:}" />
+		<property name="clientName" value="BbbScreenshare" />
 	</bean>
--->
 </beans>
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/application.conf b/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/application.conf
index 74183500ea75522d1927e5742c4f93d2722b1269..3b72838eb4bbe89bb4f2c7d26663b8c90cbd2a2b 100755
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/application.conf
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/application.conf
@@ -10,7 +10,7 @@ akka {
   loggers = ["akka.event.slf4j.Slf4jLogger"]
   loglevel = "DEBUG"
 
-  rediscala-publish-worker-dispatcher {
+  redis-publish-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
@@ -18,7 +18,7 @@ akka {
     throughput = 512
   }
 
-  rediscala-subscriber-worker-dispatcher {
+  redis-subscriber-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/screenshare-app.conf b/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/screenshare-app.conf
index 7a46eb9c45206cb1b304a93596212cf8b9595647..32a843bfaf817b1ee334bcdbe3ec5fba9b793ff5 100755
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/screenshare-app.conf
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/classes/screenshare-app.conf
@@ -10,7 +10,7 @@ akka {
   loggers = ["akka.event.slf4j.Slf4jLoggerDDD"]
   loglevel = "DEBUG"
 
-  rediscala-publish-worker-dispatcher {
+  redis-publish-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
@@ -18,7 +18,7 @@ akka {
     throughput = 512
   }
 
-  rediscala-subscriber-worker-dispatcher {
+  redis-subscriber-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml b/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml
index 1fd0b7bfc69867548f365a3042d4383967e17aa1..91e61cb370d46ab8fc3a57cefcea8e19ecf720a0 100755
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml
@@ -35,6 +35,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
     </property>
   </bean>
   
+  <bean id="screenShareApplication" class="org.bigbluebutton.app.screenshare.ScreenShareApplication">
+    <constructor-arg index="0" ref="messageBus"/>
+    <constructor-arg index="1" value="${jnlpFile}"/>
+    <constructor-arg index="2" value="${streamBaseUrl}"/>
+  </bean>
+  
+  <bean id="connectionInvokerService" class="org.bigbluebutton.app.screenshare.red5.ConnectionInvokerService"
+        init-method="start" destroy-method="stop">
+  </bean>
+  
+  <bean id="meetingManager" class="org.bigbluebutton.app.screenshare.MeetingManager"/>
+  
   <bean id="web.context" class="org.red5.server.Context" autowire="byType"/>
   
   <bean id="web.scope" class="org.red5.server.scope.WebScope" init-method="register">
@@ -48,36 +60,27 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
   
   <bean id="web.handler" class="org.bigbluebutton.app.screenshare.red5.Red5AppAdapter">
     <property name="streamBaseUrl" value="${streamBaseUrl}"/>
-    <property name="eventRecordingService" ref="eventRecordingService"/>
+    <property name="redisStorageService" ref="redisStorageService"/>
     <property name="recordingDirectory" value="${recordingDirectory}"/>
     <property name="application" ref="screenShareApplication"/>
     <property name="messageSender" ref="connectionInvokerService"/>
     <property name="meetingManager" ref="meetingManager"/>
   </bean>
 
-  <bean id="meetingManager" class="org.bigbluebutton.app.screenshare.MeetingManager"/>
-  
-  <bean id="screenshare.service" class="org.bigbluebutton.app.screenshare.red5.Red5AppService">
-    <property name="appHandler" ref="red5AppHandler"/>
-    <property name="red5RedisSender" ref="red5RedisSender"/>
-  </bean>
-
   <bean id="red5AppHandler" class="org.bigbluebutton.app.screenshare.red5.Red5AppHandler">
     <property name="application" ref="screenShareApplication"/>
     <property name="messageSender" ref="connectionInvokerService"/>
   </bean>
+  
+  <bean id="screenshare.service" class="org.bigbluebutton.app.screenshare.red5.Red5AppService">
+    <property name="appHandler" ref="red5AppHandler"/>
+  </bean>
 
   <!-- The IoHandler implementation -->
   <bean id="screenCaptureHandler" class="org.bigbluebutton.app.screenshare.server.socket.BlockStreamEventMessageHandler">
     <property name="application" ref="screenShareApplication"/>
   </bean>
 
-  <bean id="screenShareApplication" class="org.bigbluebutton.app.screenshare.ScreenShareApplication">
-    <constructor-arg index="0" ref="messageBus"/>
-    <constructor-arg index="1" value="${jnlpFile}"/>
-    <constructor-arg index="2" value="${streamBaseUrl}"/>
-  </bean>
-
   <bean id="eventListenerImp" class="org.bigbluebutton.app.screenshare.red5.EventListenerImp">
     <property name="messageSender" ref="connectionInvokerService"/>
     <property name="meetingManager" ref="meetingManager"/>
@@ -100,21 +103,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
       </property>
   </bean>
 
-  <bean id="connectionInvokerService" class="org.bigbluebutton.app.screenshare.red5.ConnectionInvokerService"
-        init-method="start" destroy-method="stop">
-  </bean>
-
-  <bean id="eventRecordingService" class="org.bigbluebutton.app.screenshare.EventRecordingService">
-    <constructor-arg index="0" value="${redis.host}"/>
-    <constructor-arg index="1" value="${redis.port}"/>
-  </bean>
-
-  <bean id="redisRecorder" class="org.bigbluebutton.app.screenshare.server.recorder.EventRecorder">
-    <constructor-arg index="0" value="${redis.host}"/>
-    <constructor-arg index="1" value="${redis.port}"/>
-  </bean>
-
+   <import resource="bbb-redis-messaging.xml"/>
 
-  <import resource="bbb-redis-pool.xml"/>
-  <import resource="bbb-red5-redis-pubsub.xml"/>
 </beans>
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/screenshare.properties b/bbb-screenshare/app/src/main/webapp/WEB-INF/screenshare.properties
index 55bd99c50f97b91fe009d1446db69a6948d04348..808616484c689c8d140c98c061b29fc0dd0b591a 100755
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/screenshare.properties
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/screenshare.properties
@@ -1,30 +1,29 @@
-#
-# NOTE: default properties.
-#
-# NOTE!!!! NOTE!!!! NOTE!!!! NOTE!!!! NOTE!!!!
-# When making changes that you don't want checked-in, do
-#   git update-index --assume-unchanged <file>
-#
-# To have git track the changes again
-# 	git update-index --no-assume-unchanged <file>
-#
-
-recordingDirectory=/usr/share/red5/webapps/screenshare/streams
-
-redis.host=127.0.0.1
-redis.port=6379
-
-
-streamBaseUrl=rtmp://192.168.23.22/screenshare
-jnlpUrl=http://192.168.23.22/screenshare
-jnlpFile=http://192.168.23.22/screenshare/screenshare.jnlp
-useH264=false
-
-# NOTES:
-# 1. GOP (group of pictures) is calculated as frameRate * keyFrameInterval
-# 2. intra-refresh=1 doesn't work in Chrome. Late comers can't view the stream as 
-#    the user missed the key frame
-# 3. keyFrameInterval is in seconds
-# 4. Make sure you encode & into &amp; as it will break the JNLP XML
-#codecOptions=crf=36&amp;preset=veryfast&amp;tune=animation,zerolatency&amp;frameRate=12.0&amp;keyFrameInterval=6
-codecOptions=crf=38&amp;preset=veryfast&amp;tune=zerolatency&amp;frameRate=5.0&amp;keyFrameInterval=5
+#
+# NOTE: default properties.
+#
+# NOTE!!!! NOTE!!!! NOTE!!!! NOTE!!!! NOTE!!!!
+# When making changes that you don't want checked-in, do
+#   git update-index --assume-unchanged <file>
+#
+# To have git track the changes again
+# 	git update-index --no-assume-unchanged <file>
+#
+
+recordingDirectory=/usr/share/red5/webapps/screenshare/streams
+
+redis.host=127.0.0.1
+redis.port=6379
+
+streamBaseUrl=rtmp://192.168.23.22/screenshare
+jnlpUrl=http://192.168.23.22/screenshare
+jnlpFile=http://192.168.23.22/screenshare/screenshare.jnlp
+useH264=false
+
+# NOTES:
+# 1. GOP (group of pictures) is calculated as frameRate * keyFrameInterval
+# 2. intra-refresh=1 doesn't work in Chrome. Late comers can't view the stream as 
+#    the user missed the key frame
+# 3. keyFrameInterval is in seconds
+# 4. Make sure you encode & into &amp; as it will break the JNLP XML
+#codecOptions=crf=36&amp;preset=veryfast&amp;tune=animation,zerolatency&amp;frameRate=12.0&amp;keyFrameInterval=6
+codecOptions=crf=38&amp;preset=veryfast&amp;tune=zerolatency&amp;frameRate=5.0&amp;keyFrameInterval=5
diff --git a/bbb-screenshare/app/src/test/java/org/bigbluebutton/deskshare/server/recorder/FileRecorderTest.java b/bbb-screenshare/app/src/test/java/org/bigbluebutton/deskshare/server/recorder/FileRecorderTest.java
deleted file mode 100755
index f5491111f761d49201584918ff900cdd51a8c3d3..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/test/java/org/bigbluebutton/deskshare/server/recorder/FileRecorderTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bigbluebutton.deskshare.server.recorder;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class FileRecorderTest {
-
-	@Test
-	public void testHello() {
-		Assert.assertEquals(true, true);
-	}
-}
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/h264/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/h264/sign-jar.sh
index 01e78770a36a2cd553bea92b1646eb6e25e27319..09225a39145e51797093fae83685c958b7b4a4bd 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/h264/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/h264/sign-jar.sh
@@ -1,18 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-linux-x86-h264.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-linux-x86.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-linux-x86.jar
-cp org/bytedeco/javacpp/linux-x86/*.so* ../src/main/resources
-cd ..
-gradle jar
-cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86-h264-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86-h264.jar
-rm -rf workdir
-rm -rf src
-
-
+FFMPEG=ffmpeg-3.0.2-1.2-linux-x86-h264.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-linux-x86.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-linux-x86.jar
+cp org/bytedeco/javacpp/linux-x86/*.so* ../src/main/resources
+cd ..
+gradle jar
+cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86-h264-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86-h264.jar
+rm -rf workdir
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/sign-jar.sh
index e82feeb760ee234e2a44d540c57802b734831493..ae658006f6ca72a6223abd5b90346d192c1c03e7 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/sign-jar.sh
@@ -1,18 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-linux-x86-svc2.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-linux-x86.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-linux-x86.jar
-cp org/bytedeco/javacpp/linux-x86/*.so* ../src/main/resources
-cd ..
-gradle jar
-cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86-svc2-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86-svc2.jar
-rm -rf workdir
-rm -rf src
-
-
+FFMPEG=ffmpeg-3.0.2-1.2-linux-x86-svc2.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-linux-x86.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-linux-x86.jar
+cp org/bytedeco/javacpp/linux-x86/*.so* ../src/main/resources
+cd ..
+gradle jar
+cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86-svc2-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86-svc2.jar
+rm -rf workdir
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/h264/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/h264/sign-jar.sh
index 2ffaf065ce97591bfc898cbd2a6cadefa6d6b715..d9c1ba9c026dbb71e1bd3ed53c167783280f669b 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/h264/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/h264/sign-jar.sh
@@ -1,17 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64-h264.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-linux-x86_64.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-linux-x86_64.jar
-cp org/bytedeco/javacpp/linux-x86_64/*.so* ../src/main/resources
-cd ..
-gradle jar
-cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86_64-h264-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86_64-h264.jar
-rm -rf workdir
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64-h264.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-linux-x86_64.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-linux-x86_64.jar
+cp org/bytedeco/javacpp/linux-x86_64/*.so* ../src/main/resources
+cd ..
+gradle jar
+cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86_64-h264-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86_64-h264.jar
+rm -rf workdir
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/sign-jar.sh
index 781bc3e084016be9de8a136cc2ad0806c86e83d9..72f4872670e8eb4171f6ff2919c98d2469535729 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/sign-jar.sh
@@ -1,17 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64-svc2.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-linux-x86_64.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-linux-x86_64.jar
-cp org/bytedeco/javacpp/linux-x86_64/*.so* ../src/main/resources
-cd ..
-gradle jar
-cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86_64-svc2-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86_64-svc2.jar
-rm -rf workdir
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64-svc2.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-linux-x86_64.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-linux-x86_64.jar
+cp org/bytedeco/javacpp/linux-x86_64/*.so* ../src/main/resources
+cd ..
+gradle jar
+cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86_64-svc2-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86_64-svc2.jar
+rm -rf workdir
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/h264/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/h264/sign-jar.sh
index 61c91813178c545c9770e7e7aa91596c78e22cdb..d8255408d3d9025dd48518325b9cf59797cd872e 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/h264/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/h264/sign-jar.sh
@@ -1,16 +1,15 @@
-FFMPEG=ffmpeg-3.0.2-1.2-macosx-x86_64-h264.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-macosx-x86_64.jar
-rm -rf src
-mkdir -p src/main/resources
-cd workdir
-jar xvf ffmpeg-macosx-x86_64.jar
-cp org/bytedeco/javacpp/macosx-x86_64/* ../src/main/resources
-cd ..
-rm -rf workdir
-gradle jar
-cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-macosx-x86_64-h264-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-macosx-x86_64-h264.jar
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-macosx-x86_64-h264.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-macosx-x86_64.jar
+rm -rf src
+mkdir -p src/main/resources
+cd workdir
+jar xvf ffmpeg-macosx-x86_64.jar
+cp org/bytedeco/javacpp/macosx-x86_64/* ../src/main/resources
+cd ..
+rm -rf workdir
+gradle jar
+cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-macosx-x86_64-h264-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-macosx-x86_64-h264.jar
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/sign-jar.sh
index 159d670c4b56cf9386e2b59600b9011f25ec7f1b..1639a806d0892dd8ca0350a592fd1ebaceccf7cc 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/sign-jar.sh
@@ -1,16 +1,15 @@
-FFMPEG=ffmpeg-3.0.2-1.2-macosx-x86_64-svc2.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-macosx-x86_64.jar
-rm -rf src
-mkdir -p src/main/resources
-cd workdir
-jar xvf ffmpeg-macosx-x86_64.jar
-cp org/bytedeco/javacpp/macosx-x86_64/* ../src/main/resources
-cd ..
-rm -rf workdir
-gradle jar
-cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-macosx-x86_64-svc2-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-macosx-x86_64-svc2.jar
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-macosx-x86_64-svc2.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-macosx-x86_64.jar
+rm -rf src
+mkdir -p src/main/resources
+cd workdir
+jar xvf ffmpeg-macosx-x86_64.jar
+cp org/bytedeco/javacpp/macosx-x86_64/* ../src/main/resources
+cd ..
+rm -rf workdir
+gradle jar
+cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-macosx-x86_64-svc2-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-macosx-x86_64-svc2.jar
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/h264/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/h264/sign-jar.sh
index 1fbfa0ec41526a3a280e8e6fad206b611f733a8f..4f7c36064ba816126685d5410e81bf7b1fbc599b 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/h264/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/h264/sign-jar.sh
@@ -1,17 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-windows-x86-h264.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-windows-x86.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-windows-x86.jar
-cp org/bytedeco/javacpp/windows-x86/*.dll ../src/main/resources
-cd ..
-rm -rf workdir
-gradle jar
-cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86-h264-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86-h264.jar
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-windows-x86-h264.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-windows-x86.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-windows-x86.jar
+cp org/bytedeco/javacpp/windows-x86/*.dll ../src/main/resources
+cd ..
+rm -rf workdir
+gradle jar
+cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86-h264-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86-h264.jar
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/sign-jar.sh
index 1e8a5d3afb9c94885b7053e981e22560c2e9b39e..320f34680b98c219c449c9eacd21a611ca31ae06 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/sign-jar.sh
@@ -1,17 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-windows-x86-svc2.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-windows-x86.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-windows-x86.jar
-cp org/bytedeco/javacpp/windows-x86/*.dll ../src/main/resources
-cd ..
-rm -rf workdir
-gradle jar
-cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86-svc2-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86-svc2.jar
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-windows-x86-svc2.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-windows-x86.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-windows-x86.jar
+cp org/bytedeco/javacpp/windows-x86/*.dll ../src/main/resources
+cd ..
+rm -rf workdir
+gradle jar
+cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86-svc2-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86-svc2.jar
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/h264/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/h264/sign-jar.sh
index 94ed509cc73fc2cfc9d6bce5a50e71b46ddbf683..7ace75cc22b9316e8bea64d1aa17e372858be86d 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/h264/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/h264/sign-jar.sh
@@ -1,17 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64-h264.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-windows-x86_64.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-windows-x86_64.jar
-cp org/bytedeco/javacpp/windows-x86_64/*.dll ../src/main/resources
-cd ..
-rm -rf workdir
-gradle jar
-cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86_64-h264-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86_64-h264.jar
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64-h264.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-windows-x86_64.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-windows-x86_64.jar
+cp org/bytedeco/javacpp/windows-x86_64/*.dll ../src/main/resources
+cd ..
+rm -rf workdir
+gradle jar
+cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86_64-h264-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86_64-h264.jar
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/sign-jar.sh b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/sign-jar.sh
index 4b8c8c1023acdb7649988c76470fbb13ebac00ee..0c67733b6a4defa15d824876a17133ffbe6e9962 100755
--- a/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/sign-jar.sh
+++ b/bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/sign-jar.sh
@@ -1,17 +1,16 @@
-FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64-svc2.jar
-mkdir workdir
-cp $FFMPEG workdir/ffmpeg-windows-x86_64.jar
-rm -rf src
-mkdir -p src/main/resources
-mkdir -p src/main/java
-cd workdir
-jar xvf ffmpeg-windows-x86_64.jar
-cp org/bytedeco/javacpp/windows-x86_64/*.dll ../src/main/resources
-cd ..
-rm -rf workdir
-gradle jar
-cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86_64-svc2-unsigned.jar
-ant sign-jar
-cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86_64-svc2.jar
-rm -rf src
-
+FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64-svc2.jar
+mkdir workdir
+cp $FFMPEG workdir/ffmpeg-windows-x86_64.jar
+rm -rf src
+mkdir -p src/main/resources
+mkdir -p src/main/java
+cd workdir
+jar xvf ffmpeg-windows-x86_64.jar
+cp org/bytedeco/javacpp/windows-x86_64/*.dll ../src/main/resources
+cd ..
+rm -rf workdir
+gradle jar
+cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86_64-svc2-unsigned.jar
+ant sign-jar
+cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86_64-svc2.jar
+rm -rf src
diff --git a/bbb-screenshare/jws/native-libs/unsigned-jars/sign-ffmpeg.sh b/bbb-screenshare/jws/native-libs/unsigned-jars/sign-ffmpeg.sh
index 6cb98b0ea9930b6e4a4863e4c46fa0dc3d435a05..0ea0ec71b4c7e1e6115076ad991b3bfc52b603d0 100755
--- a/bbb-screenshare/jws/native-libs/unsigned-jars/sign-ffmpeg.sh
+++ b/bbb-screenshare/jws/native-libs/unsigned-jars/sign-ffmpeg.sh
@@ -1,16 +1,15 @@
-FFMPEG=ffmpeg-3.0.2-1.2.jar
-if [ -d "workdir" ]; then
-  rm -rf workdir
-fi
-mkdir workdir
-cp $FFMPEG workdir
-cd workdir
-jar xf $FFMPEG
-rm $FFMPEG
-rm -rf META-INF
-jar cf ffmpeg.jar *
-cd ..
-ant sign-ffmpeg-jar
-cp workdir/ffmpeg.jar ../../../app/jws/lib/
-rm -rf workdir
-
+FFMPEG=ffmpeg-3.0.2-1.2.jar
+if [ -d "workdir" ]; then
+  rm -rf workdir
+fi
+mkdir workdir
+cp $FFMPEG workdir
+cd workdir
+jar xf $FFMPEG
+rm $FFMPEG
+rm -rf META-INF
+jar cf ffmpeg.jar *
+cd ..
+ant sign-ffmpeg-jar
+cp workdir/ffmpeg.jar ../../../app/jws/lib/
+rm -rf workdir
diff --git a/bbb-screenshare/jws/webstart/build.sh b/bbb-screenshare/jws/webstart/build.sh
index 7074eba05053fb7e50983b4a92274174da04f6fd..fec75ea03c9b57d17e66cce5ad66a63e48f080a3 100755
--- a/bbb-screenshare/jws/webstart/build.sh
+++ b/bbb-screenshare/jws/webstart/build.sh
@@ -1,11 +1,10 @@
-if [ -d "lib" ]; then
-  rm -rf lib
-fi
-mkdir lib
-cp ../../app/jws/lib/ffmpeg.jar lib
-gradle clean
-gradle jar
-ant sign-jar
-cp build/libs/javacv-screenshare-0.0.1.jar ../../app/jws/lib/
-rm -rf lib
-
+if [ -d "lib" ]; then
+  rm -rf lib
+fi
+mkdir lib
+cp ../../app/jws/lib/ffmpeg.jar lib
+gradle clean
+gradle jar
+ant sign-jar
+cp build/libs/javacv-screenshare-0.0.1.jar ../../app/jws/lib/
+rm -rf lib
diff --git a/bbb-screenshare/jws/webstart/deploy.sh b/bbb-screenshare/jws/webstart/deploy.sh
index d8322cc8028df17d13f92a3e5de60fec086d9173..e49c761f5592b2ee5439484e40c99141912801c7 100755
--- a/bbb-screenshare/jws/webstart/deploy.sh
+++ b/bbb-screenshare/jws/webstart/deploy.sh
@@ -1,2 +1 @@
-cp build/libs/javacv-screenshare-0.0.1.jar /usr/share/red5/webapps/screenshare/lib
-
+cp build/libs/javacv-screenshare-0.0.1.jar /usr/share/red5/webapps/screenshare/lib
diff --git a/bbb-video/build.gradle b/bbb-video/build.gradle
index 88d9a056cc948c10ab31da12063df7dea0fb82cc..a174e2254606d89c26178d1069e5ac98cc8e2a12 100755
--- a/bbb-video/build.gradle
+++ b/bbb-video/build.gradle
@@ -17,6 +17,13 @@ repositories {
   mavenLocal()
 }
 
+configurations {
+    runtime.exclude group: "org.slf4j", module: "slf4j-api"
+    runtime.exclude group: "org.red5", module: "red5-server"
+    runtime.exclude group: "org.red5", module: "red5-server-common"
+    runtime.exclude group: "org.red5", module: "red5-io"
+}
+
 dependencies {
   // Servlet
   providedCompile 'javax.servlet:servlet-api:2.5@jar'
@@ -28,10 +35,11 @@ dependencies {
 
   // Spring
   providedCompile 'org.springframework:spring-web:4.3.12.RELEASE@jar'
-  providedCompile  'org.springframework:spring-beans:4.3.12.RELEASE@jar'
+  providedCompile 'org.springframework:spring-beans:4.3.12.RELEASE@jar'
   providedCompile 'org.springframework:spring-context:4.3.12.RELEASE@jar'
   providedCompile 'org.springframework:spring-core:4.3.12.RELEASE@jar'
 
+  // Red5
   providedCompile 'org.red5:red5-server:1.0.10-M5@jar'
   providedCompile 'org.red5:red5-server-common:1.0.10-M5@jar'
   providedCompile 'org.red5:red5-io:1.0.10-M5@jar'
@@ -49,23 +57,12 @@ dependencies {
   providedCompile 'org.springframework:spring-aop:4.3.12.RELEASE@jar'
   compile 'aopalliance:aopalliance:1.0@jar'
 
-  // Testing
-  compile 'org.easymock:easymock:2.4@jar'
-
-  // Testing
-  testRuntime 'org.easymock:easymock:2.4@jar'
-
   //redis
-  compile 'redis.clients:jedis:2.9.0'
-  compile 'org.apache.commons:commons-pool2:2.3'
-  compile 'com.google.code.gson:gson:2.5'
-
-  compile 'org.apache.commons:commons-lang3:3.7'
-  compile 'org.bigbluebutton:bbb-common-message_2.12:0.0.19-SNAPSHOT'
-}
+  compile 'org.apache.commons:commons-pool2:2.6.0'
+  compile 'com.google.code.gson:gson:2.8.5'
 
-test {
-    useTestNG()
+  providedCompile 'org.apache.commons:commons-lang3:3.7'
+  compile 'org.bigbluebutton:bbb-common-message_2.12:0.0.20-SNAPSHOT'
 }
 
 war.doLast {
@@ -76,6 +73,7 @@ war.doLast {
 task deploy() << {
 	def red5AppsDir = '/usr/share/red5/webapps'
 	def videoDir = new File("${red5AppsDir}/video")
+    println "Deleting $videoDir"
 	if (videoDir.exists()) ant.delete(dir: videoDir)
 	ant.mkdir(dir: videoDir)
 	ant.copy(todir: videoDir) {
diff --git a/bbb-video/deploy.sh b/bbb-video/deploy.sh
index ff71c3ac7c685a5db422d9161f25a82b6c186300..b7cab36a4bc4e2ff6e2b72d8bb9bf36079ce3149 100755
--- a/bbb-video/deploy.sh
+++ b/bbb-video/deploy.sh
@@ -1,11 +1,10 @@
 #!/bin/bash
 # deploying 'bigbluebutton-apps' to /usr/share/red5/webapps
 
-sudo chown -R red5.red5 /usr/share/red5/webapps
+sudo chmod -R 777 /usr/share/red5/webapps/*
 
 gradle clean
 gradle resolveDeps
 gradle war deploy
 
-sudo chown -R red5.red5 /usr/share/red5/webapps
-
+sudo chown -R red5:red5 /usr/share/red5/webapps
diff --git a/bbb-video/src/main/java/org/bigbluebutton/app/video/EventRecordingService.java b/bbb-video/src/main/java/org/bigbluebutton/app/video/EventRecordingService.java
deleted file mode 100755
index 4bdec5c1df4e6b7f547df283519762cddc6c5006..0000000000000000000000000000000000000000
--- a/bbb-video/src/main/java/org/bigbluebutton/app/video/EventRecordingService.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
-package org.bigbluebutton.app.video;
-
-import java.util.Map;
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.Protocol;
-
-public class EventRecordingService {
-	private static Logger log = Red5LoggerFactory.getLogger(EventRecordingService.class, "video");
-
-	private static final String COLON = ":";
-
-	private JedisPool redisPool;
-	private final String  host;
-	private final int port;
-	private final int keyExpiry;
-	
-	public EventRecordingService(String host, int port, int keyExpiry) {
-		this.host = host;
-		this.port = port;
-		this.keyExpiry = keyExpiry;
-	}
-	
-	public void record(String meetingId, Map<String, String> event) {
-		Jedis jedis = redisPool.getResource();
-		try {
-			Long msgid = jedis.incr("global:nextRecordedMsgId");
-			String key = "recording:" + meetingId + COLON + msgid;
-			jedis.hmset(key, event);
-			/**
-			 * We set the key to expire after 14 days as we are still
-			 * recording the event into redis even if the meeting is not
-			 * recorded. (ralam sept 23, 2015)
-			 */
-			jedis.expire(key, keyExpiry);
-			key = "meeting:" + meetingId + COLON + "recordings";
-			jedis.rpush(key, msgid.toString());
-			jedis.expire(key, keyExpiry);
-		} catch (Exception e) {
-			log.warn("Cannot record the info meeting:" + meetingId, e);
-		} finally {
-			jedis.close();
-		}
-
-	}
-
-	public void stop() {
-
-	}
-
-	public void start() {
-		// Set the name of this client to be able to distinguish when doing
-		// CLIENT LIST on redis-cli
-		redisPool = new JedisPool(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT, null,
-			Protocol.DEFAULT_DATABASE, "BbbRed5AppsPub");
-	}
-}
diff --git a/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java b/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java
index 3b48025cc4ff4462867d0dae92ed5d4b14c6d1b0..054b5ca6f0fc5b8b9f0146f5e8f5d45da2a33c8b 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java
+++ b/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java
@@ -21,11 +21,16 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
 import org.bigbluebutton.app.video.converter.H263Converter;
 import org.bigbluebutton.app.video.converter.VideoRotator;
+import org.bigbluebutton.common2.redis.RedisStorageService;
 import org.bigbluebutton.red5.pubsub.MessagePublisher;
 import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.adapter.MultiThreadedApplicationAdapter;
@@ -39,11 +44,9 @@ import org.red5.server.api.stream.ISubscriberStream;
 import org.red5.server.scheduling.QuartzSchedulingService;
 import org.red5.server.stream.ClientBroadcastStream;
 import org.slf4j.Logger;
-import com.google.gson.Gson;
 import org.springframework.util.StringUtils;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
+
+import com.google.gson.Gson;
 
 
 public class VideoApplication extends MultiThreadedApplicationAdapter {
@@ -53,7 +56,7 @@ public class VideoApplication extends MultiThreadedApplicationAdapter {
     private QuartzSchedulingService scheduler;
 
     private MessagePublisher publisher;
-    private EventRecordingService recordingService;
+    private RedisStorageService recordingService;
     private final Map<String, IStreamListener> streamListeners = new HashMap<String, IStreamListener>();
 
     private int packetTimeout = 10000;
@@ -518,7 +521,7 @@ public class VideoApplication extends MultiThreadedApplicationAdapter {
 			event.put("stream", stream.getPublishedName());
 			event.put("duration", new Long(publishDuration).toString());
 			event.put("eventName", "StopWebcamShareEvent");
-			recordingService.record(scopeName, event);
+			recordingService.recordAndExpire(scopeName, event);
 		}
 	}
 
@@ -526,7 +529,7 @@ public class VideoApplication extends MultiThreadedApplicationAdapter {
 		this.packetTimeout = timeout;
 	}
 
-	public void setEventRecordingService(EventRecordingService s) {
+	public void setEventRecordingService(RedisStorageService s) {
 		recordingService = s;
 	}
 
diff --git a/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoStreamListener.java b/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoStreamListener.java
index d1cb002298338ea060787a12cfc30b0e8f5e0728..f235e0574780141a6a14f82ef028fedd7f7de873 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoStreamListener.java
+++ b/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoStreamListener.java
@@ -18,24 +18,24 @@
 package org.bigbluebutton.app.video;
 
 
+import java.text.SimpleDateFormat;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.mina.core.buffer.IoBuffer;
+import org.bigbluebutton.common2.redis.RedisStorageService;
+import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.api.scheduling.IScheduledJob;
 import org.red5.server.api.scheduling.ISchedulingService;
-import org.red5.server.api.scope.IScope;
 import org.red5.server.api.stream.IBroadcastStream;
 import org.red5.server.api.stream.IStreamListener;
 import org.red5.server.api.stream.IStreamPacket;
 import org.red5.server.net.rtmp.event.VideoData;
 import org.red5.server.scheduling.QuartzSchedulingService;
 import org.slf4j.Logger;
-import org.red5.logging.Red5LoggerFactory;
 
 import com.google.gson.Gson;
-import java.text.SimpleDateFormat;
 
 /**
  * Class to listen for the first video packet of the webcam.
@@ -55,7 +55,7 @@ import java.text.SimpleDateFormat;
 public class VideoStreamListener implements IStreamListener {
   private static final Logger log = Red5LoggerFactory.getLogger(VideoStreamListener.class, "video");
 
-  private EventRecordingService recordingService;
+  private RedisStorageService recordingService;
   private volatile boolean firstPacketReceived = false;
 
   // Maximum time between video packets
@@ -98,7 +98,7 @@ public class VideoStreamListener implements IStreamListener {
   public VideoStreamListener(String meetingId, String streamId, Boolean record,
                              String userId, int packetTimeout,
                              QuartzSchedulingService scheduler,
-                             EventRecordingService recordingService) {
+                             RedisStorageService recordingService) {
     this.meetingId = meetingId;
     this.streamId = streamId;
     this.record = record;
@@ -160,7 +160,7 @@ public class VideoStreamListener implements IStreamListener {
 					event.put(DATE, sdf.format(recordingStartTime));
           event.put("eventName", "StartWebcamShareEvent");
 
-          recordingService.record(meetingId, event);
+          recordingService.recordAndExpire(meetingId, event);
 
 					Gson gson = new Gson();
 					String logStr = gson.toJson(event);
@@ -229,7 +229,7 @@ public class VideoStreamListener implements IStreamListener {
 			event.put(DATE, sdf.format(now));
       event.put("eventName", "StopWebcamShareEvent");
 
-      recordingService.record(meetingId, event);
+      recordingService.recordAndExpire(meetingId, event);
 
 			Gson gson = new Gson();
 			String logStr = gson.toJson(event);
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MeetingMessageHandler.java b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MeetingMessageHandler.java
index 14d8b61a8e3f40a1bbe8f1ae69056864cf6740b2..13b183125a22ae66a56f21f4ffe334fd3af045f0 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MeetingMessageHandler.java
+++ b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MeetingMessageHandler.java
@@ -1,19 +1,20 @@
 package org.bigbluebutton.red5.pubsub;
 
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
 import org.bigbluebutton.app.video.ConnectionInvokerService;
 import org.bigbluebutton.app.video.MeetingManager;
+import org.bigbluebutton.common2.redis.pubsub.MessageHandler;
 import org.bigbluebutton.red5.pubsub.message.RecordChapterBreakMessage;
 import org.bigbluebutton.red5.pubsub.message.ValidateConnTokenRespMsg;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
 public class MeetingMessageHandler implements MessageHandler {
     private static Logger log = Red5LoggerFactory.getLogger(MeetingMessageHandler.class, "video");
 
-
     private final String HEADER = "header";
     private final String NAME = "name";
     private final String BODY = "body";
@@ -61,8 +62,7 @@ public class MeetingMessageHandler implements MessageHandler {
             String logStr = gson.toJson(body);
 
             log.debug("HANDLE: {}", logStr);
-            if (body.has(MEETING_ID) && body.has(USERID)
-                    && body.has(AUTHZED) && body.has(CONN) && body.has(APP)) {
+            if (body.has(MEETING_ID) && body.has(USERID) && body.has(AUTHZED) && body.has(CONN) && body.has(APP)) {
 
                 String meetingId = body.get(MEETING_ID).getAsString();
                 String userId = body.get(USERID).getAsString();
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageHandler.java b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageHandler.java
deleted file mode 100755
index 8f197312c290d0ef21e0baed37478d9d7bfb94e3..0000000000000000000000000000000000000000
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageHandler.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.bigbluebutton.red5.pubsub;
-
-public interface MessageHandler {
-    void handleMessage(String pattern, String channel, String message);
-}
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java
index 0326ff3651835846f109ccab38c23b7978cd580b..f2619b6341e2e52da76d55349c42c1548915a677 100755
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java
+++ b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java
@@ -1,11 +1,21 @@
 package org.bigbluebutton.red5.pubsub;
 
 
-import com.google.gson.Gson;
-import org.bigbluebutton.common2.msgs.*;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.bigbluebutton.common2.msgs.BbbClientMsgHeader;
+import org.bigbluebutton.common2.msgs.BbbCoreBaseHeader;
+import org.bigbluebutton.common2.msgs.UserBroadcastCamStartMsg;
+import org.bigbluebutton.common2.msgs.UserBroadcastCamStartMsgBody;
+import org.bigbluebutton.common2.msgs.UserBroadcastCamStopMsg;
+import org.bigbluebutton.common2.msgs.UserBroadcastCamStopMsgBody;
+import org.bigbluebutton.common2.msgs.ValidateConnAuthTokenSysMsg;
+import org.bigbluebutton.common2.msgs.ValidateConnAuthTokenSysMsgBody;
+import org.bigbluebutton.common2.redis.pubsub.MessageSender;
+
+import com.google.gson.Gson;
+
 public class MessagePublisher {
 
 	private MessageSender sender;
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageReceiver.java b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageReceiver.java
deleted file mode 100755
index fc215cdba5811e3f5ea061a18268c1bca4d6e821..0000000000000000000000000000000000000000
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageReceiver.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bigbluebutton.red5.pubsub;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPubSub;
-import redis.clients.jedis.exceptions.JedisConnectionException;
-
-public class MessageReceiver {
-    private static Logger log = Red5LoggerFactory.getLogger(MessageReceiver.class, "video");
-
-    private ReceivedMessageHandler handler;
-
-    private Jedis jedis;
-    private volatile boolean receiveMessage = false;
-
-    private final Executor msgReceiverExec = Executors.newSingleThreadExecutor();
-    private final Executor runExec = Executors.newSingleThreadExecutor();
-
-    private final String FROM_BBB_APPS_PATTERN = "from-akka-apps-redis-channel";
-
-    private String host;
-    private int port;
-
-    public void stop() {
-        receiveMessage = false;
-    }
-
-    public void start() {
-        log.info("Ready to receive messages from Redis pubsub.");
-        try {
-            receiveMessage = true;
-            jedis = new Jedis(host, port);
-            // Set the name of this client to be able to distinguish when doing
-            // CLIENT LIST on redis-cli
-            jedis.clientSetname("BbbRed5VideoSub");
-
-            Runnable messageReceiver = new Runnable() {
-                public void run() {
-                    if (receiveMessage) {
-                        try {
-                            jedis.subscribe(new PubSubListener(), FROM_BBB_APPS_PATTERN);
-                        } catch(JedisConnectionException ex) {
-                            log.warn("Exception on Jedis connection. Resubscribing to pubsub.");
-                            start();
-                        } catch (Exception e) {
-                            log.error("Error resubscribing to channels: " + e.getMessage());
-                        }
-                    }
-                }
-            };
-            msgReceiverExec.execute(messageReceiver);
-        } catch (Exception e) {
-            log.error("Error subscribing to channels: " + e.getMessage());
-        }
-    }
-
-    public void setHost(String host){
-        this.host = host;
-    }
-
-    public void setPort(int port) {
-        this.port = port;
-    }
-
-    public void setMessageHandler(ReceivedMessageHandler handler) {
-        this.handler = handler;
-    }
-
-    private class PubSubListener extends JedisPubSub {
-
-        public PubSubListener() {
-            super();
-        }
-
-        @Override
-        public void onMessage(String channel, String message) {
-            // Not used.
-            Runnable task = new Runnable() {
-                public void run() {
-                    handler.handleMessage("", channel, message);
-                }
-            };
-
-            runExec.execute(task);
-        }
-
-        @Override
-        public void onPMessage(final String pattern, final String channel, final String message) {
-            System.out.println("RECEIVED onPMessage" + channel + " message=\n" + message);
-            Runnable task = new Runnable() {
-                public void run() {
-                    handler.handleMessage(pattern, channel, message);
-                }
-            };
-
-            runExec.execute(task);
-        }
-
-        @Override
-        public void onPSubscribe(String pattern, int subscribedChannels) {
-            log.debug("Subscribed to the pattern: " + pattern);
-        }
-
-        @Override
-        public void onPUnsubscribe(String pattern, int subscribedChannels) {
-            // Not used.
-        }
-
-        @Override
-        public void onSubscribe(String channel, int subscribedChannels) {
-            // Not used.
-        }
-
-        @Override
-        public void onUnsubscribe(String channel, int subscribedChannels) {
-            // Not used.
-        }
-    }
-}
-
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageSender.java b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageSender.java
deleted file mode 100755
index 0b732de4e99d98c2a1d6dda54777fa585f1a6eed..0000000000000000000000000000000000000000
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageSender.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bigbluebutton.red5.pubsub;
-
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.Protocol;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-
-public class MessageSender {
-	private static Logger log = Red5LoggerFactory.getLogger(MessageSender.class, "bigbluebutton");
-	
-	private JedisPool redisPool;
-	private volatile boolean sendMessage = false;
-	
-	private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
-	private final Executor runExec = Executors.newSingleThreadExecutor();
-	private BlockingQueue<MessageToSend> messages = new LinkedBlockingQueue<MessageToSend>();
-	private String host;
-	private int port;
-
-	public void stop() {
-		sendMessage = false;
-		redisPool.destroy();
-	}
-	
-	public void start() {	
-
-		GenericObjectPoolConfig config = new GenericObjectPoolConfig();
-		config.setMaxTotal(32);
-		config.setMaxIdle(8);
-		config.setMinIdle(1);
-		config.setTestOnBorrow(true);
-		config.setTestOnReturn(true);
-		config.setTestWhileIdle(true);
-		config.setNumTestsPerEvictionRun(12);
-		config.setMaxWaitMillis(5000);
-		config.setTimeBetweenEvictionRunsMillis(60000);
-		config.setBlockWhenExhausted(true);
-
-		// Set the name of this client to be able to distinguish when doing
-		// CLIENT LIST on redis-cli
-		redisPool = new JedisPool(config, host, port, Protocol.DEFAULT_TIMEOUT, null,
-				Protocol.DEFAULT_DATABASE, "BbbRed5VideoPub");
-
-		log.info("Redis message publisher starting!");
-
-		try {
-			sendMessage = true;
-			
-			Runnable messageSender = new Runnable() {
-				public void run() {
-					while (sendMessage) {
-						try {
-							MessageToSend msg = messages.take();
-							publish(msg.getChannel(), msg.getMessage());
-						} catch (InterruptedException e) {
-							log.warn("Failed to get org.bigbluebutton.red5.pubsub.message from queue.");
-						}
-					}
-				}
-			};
-			msgSenderExec.execute(messageSender);
-		} catch (Exception e) {
-			log.error("Error subscribing to channels: " + e.getMessage());
-		}			
-	}
-	
-	public void send(String channel, String message) {
-		MessageToSend msg = new MessageToSend(channel, message);
-		messages.add(msg);
-	}
-	
-	private void publish(final String channel, final String message) {
-		Runnable task = new Runnable() {
-			public void run() {
-				Jedis jedis = redisPool.getResource();
-				try {
-					jedis.publish(channel, message);
-				} catch(Exception e){
-					log.warn("Cannot publish the org.bigbluebutton.red5.pubsub.message to redis", e);
-				} finally {
-					redisPool.returnResource(jedis);
-				}
-			}
-		};
-		
-		runExec.execute(task);
-	}
-
-
-	public void setHost(String host){
-		this.host = host;
-	}
-
-	public void setPort(int port) {
-		this.port = port;
-	}
-}
diff --git a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageToSend.java b/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageToSend.java
deleted file mode 100755
index 3ae3874039b4637af954bf7d5d176bc80d268405..0000000000000000000000000000000000000000
--- a/bbb-video/src/main/java/org/bigbluebutton/red5/pubsub/MessageToSend.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bigbluebutton.red5.pubsub;
-
-public class MessageToSend {
-	private final String channel;
-	private final String message;
-	
-	public MessageToSend(String channel, String message) {
-		this.channel = channel;
-		this.message = message;
-	}
-	
-	public String getChannel() {
-		return channel;
-	}
-	
-	public String getMessage() {
-		return message;
-	}
-}
diff --git a/bbb-video/src/main/webapp/WEB-INF/bbb-redis-messaging.xml b/bbb-video/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
new file mode 100755
index 0000000000000000000000000000000000000000..918167fe436ec37521319e311f84e2f639da9775
--- /dev/null
+++ b/bbb-video/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+
+This program is free software; you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 3.0 of the License, or (at your option) any later
+version.
+
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+			http://www.springframework.org/schema/util 
+			http://www.springframework.org/schema/util/spring-util-2.0.xsd
+			">
+
+	<bean id="meetingMessageHandler" class="org.bigbluebutton.red5.pubsub.MeetingMessageHandler">
+		<property name="meetingManager" ref="meetingManager"/>
+		<property name="connInvokerService" ref="connInvokerService"/>
+	</bean>
+
+	<bean id="receivedMessageHandler" class="org.bigbluebutton.common2.redis.pubsub.ReceivedMessageHandler"
+		  init-method="start" destroy-method="stop">
+	</bean>
+
+	<bean id="redisStorageService"
+		class="org.bigbluebutton.common2.redis.RedisStorageService"
+		init-method="start" destroy-method="stop">
+		<property name="host" value="${redis.host}" />
+		<property name="port" value="${redis.port}" />
+		<property name="password" value="${redis.password:}" />
+		<property name="expireKey" value="${redis.keyExpiry}" />
+		<property name="clientName" value="BbbRed5VideoStore" />
+	</bean>
+	
+	<bean id="messageReceiver" class="org.bigbluebutton.common2.redis.pubsub.MessageReceiver"
+		  init-method="start" destroy-method="stop">
+		<property name="host" value="${redis.host}" />
+		<property name="port" value="${redis.port}" />
+		<property name="password" value="${redis.password:}" />
+		<property name="clientName" value="BbbRed5VideoReceiver" />
+		<property name="messageHandler" ref="receivedMessageHandler"/>
+	</bean>
+
+    <bean id="redisSender" class="org.bigbluebutton.common2.redis.pubsub.MessageSender" 
+                    init-method="start" destroy-method="stop">
+		<property name="host" value="${redis.host}" />
+		<property name="port" value="${redis.port}" />
+		<property name="password" value="${redis.password:}" />
+		<property name="clientName" value="BbbRed5VideoSender" />
+    </bean>
+    
+    <bean id="redisPublisher" class="org.bigbluebutton.red5.pubsub.MessagePublisher">
+        <property name="messageSender" ref="redisSender"/>
+    </bean>
+    
+	<bean id="messageDistributor" class="org.bigbluebutton.common2.redis.pubsub.MessageDistributor">
+		<property name="messageHandler" ref="receivedMessageHandler"/>
+		<property name="messageListeners">
+			<set>
+				<ref bean="meetingMessageHandler" />
+			</set>
+		</property>
+	</bean>
+    
+</beans>
diff --git a/bbb-video/src/main/webapp/WEB-INF/bbb-redis-pool.xml b/bbb-video/src/main/webapp/WEB-INF/bbb-redis-pool.xml
deleted file mode 100755
index 2d3cfd9098a5141b93f859828d18f65c5a5348b7..0000000000000000000000000000000000000000
--- a/bbb-video/src/main/webapp/WEB-INF/bbb-redis-pool.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-
-Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-
-This program is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free Software
-Foundation; either version 3.0 of the License, or (at your option) any later
-version.
-
-BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans
-			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-			http://www.springframework.org/schema/util 
-			http://www.springframework.org/schema/util/spring-util-2.0.xsd
-			">
-
-    
-</beans>
diff --git a/bbb-video/src/main/webapp/WEB-INF/bigbluebutton-video.properties b/bbb-video/src/main/webapp/WEB-INF/bigbluebutton-video.properties
index 5f8030de0c73cfb61b1eb9fa6816b9cec420445a..c8b4ea2405ecdd8772b5af5a7ee2aebdbe15a2f5 100755
--- a/bbb-video/src/main/webapp/WEB-INF/bigbluebutton-video.properties
+++ b/bbb-video/src/main/webapp/WEB-INF/bigbluebutton-video.properties
@@ -1,4 +1,5 @@
-redis.host=127.0.0.1
-redis.port=6379
-# recording keys should expire in 14 days
-redis.keyExpiry=1209600
+redis.host=127.0.0.1
+redis.port=6379
+redis.password=
+# recording keys should expire in 14 days
+redis.keyExpiry=1209600
diff --git a/bbb-video/src/main/webapp/WEB-INF/red5-web.xml b/bbb-video/src/main/webapp/WEB-INF/red5-web.xml
index e4c7b3adc83ee1d7e20c2a2f0ca62ddb48976a4f..fc80adb5503af93a9b1ff65584cf5f5928bc6df5 100755
--- a/bbb-video/src/main/webapp/WEB-INF/red5-web.xml
+++ b/bbb-video/src/main/webapp/WEB-INF/red5-web.xml
@@ -21,8 +21,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:lang="http://www.springframework.org/schema/lang"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
-                           http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
+       xsi:schemaLocation="http://www.springframework.org/schema/beans 
+                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+                           http://www.springframework.org/schema/lang 
+                           http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
 
 	<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 	    <property name="locations">
@@ -32,6 +34,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 	    	</list>
 	    </property>
 	</bean>
+	
+	<bean id="meetingManager" class="org.bigbluebutton.app.video.MeetingManager"/>
+	
+	<bean id="connInvokerService" class="org.bigbluebutton.app.video.ConnectionInvokerService"
+		  init-method="start" destroy-method="stop"/>
 
 	<bean id="web.context" class="org.red5.server.Context"
 		autowire="byType" />
@@ -44,59 +51,15 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 		<property name="contextPath" value="${webapp.contextPath}" />
 		<property name="virtualHosts" value="${webapp.virtualHosts}" />
 	</bean>
-
+	
 	<bean id="web.handler" class="org.bigbluebutton.app.video.VideoApplication">
 	   <property name="packetTimeout" value="10000"/>
-		<property name="eventRecordingService" ref="redisRecorder"/>
+		<property name="eventRecordingService" ref="redisStorageService"/>
 		<property name="messagePublisher" ref="redisPublisher"/>
 		<property name="meetingManager" ref="meetingManager"/>
 		<property name="connInvokerService" ref="connInvokerService"/>
 	</bean>
+	
+	<import resource="bbb-redis-messaging.xml"/>
 
-	<bean id="connInvokerService" class="org.bigbluebutton.app.video.ConnectionInvokerService"
-		  init-method="start" destroy-method="stop"/>
-
-	<bean id="meetingManager" class="org.bigbluebutton.app.video.MeetingManager"/>
-
-    <bean id="redisPublisher" class="org.bigbluebutton.red5.pubsub.MessagePublisher">
-        <property name="messageSender" ref="redisSender"/>
-    </bean>
-    
-	<bean id="redisRecorder" class="org.bigbluebutton.app.video.EventRecordingService"
-		  init-method="start" destroy-method="stop">
-        <constructor-arg index="0" value="${redis.host}"/>
-        <constructor-arg index="1" value="${redis.port}"/>
-        <constructor-arg index="2" value="${redis.keyExpiry}"/>
-    </bean>
-
-	<bean id="messageReceiver" class="org.bigbluebutton.red5.pubsub.MessageReceiver"
-		  init-method="start" destroy-method="stop">
-		<property name="host" value="${redis.host}"/>
-		<property name="port" value="${redis.port}"/>
-		<property name="messageHandler" ref="receivedMessageHandler"/>
-	</bean>
-
-	<bean id="messageDistributor" class="org.bigbluebutton.red5.pubsub.MessageDistributor">
-		<property name="messageHandler" ref="receivedMessageHandler"/>
-		<property name="messageListeners">
-			<set>
-				<ref bean="meetingMessageHandler" />
-			</set>
-		</property>
-	</bean>
-
-	<bean id="meetingMessageHandler" class="org.bigbluebutton.red5.pubsub.MeetingMessageHandler">
-		<property name="meetingManager" ref="meetingManager"/>
-		<property name="connInvokerService" ref="connInvokerService"/>
-	</bean>
-
-	<bean id="receivedMessageHandler" class="org.bigbluebutton.red5.pubsub.ReceivedMessageHandler"
-		  init-method="start" destroy-method="stop">
-	</bean>
-
-    <bean id="redisSender" class="org.bigbluebutton.red5.pubsub.MessageSender" 
-                    init-method="start" destroy-method="stop">
-		<property name="host" value="${redis.host}"/>
-		<property name="port" value="${redis.port}"/>
-    </bean>
 </beans>
diff --git a/bbb-video/src/main/webapp/WEB-INF/web.xml b/bbb-video/src/main/webapp/WEB-INF/web.xml
index af135b12d6da7c523b765161022e49ef73f4d134..24e0b09f9ff3286ff18d193120143b2d298121b3 100755
--- a/bbb-video/src/main/webapp/WEB-INF/web.xml
+++ b/bbb-video/src/main/webapp/WEB-INF/web.xml
@@ -29,7 +29,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 		<param-name>webAppRootKey</param-name>
 		<param-value>/video</param-value>
 	</context-param>
-		
 
     <listener>
         <listener-class>org.red5.logging.ContextLoggingListener</listener-class>
diff --git a/bbb-voice/build.gradle b/bbb-voice/build.gradle
index e364181721d6b9c86df523f55c5b1fc51c0ed0d5..8828b83c349c1b22150e5d4b425191e86d16ee29 100755
--- a/bbb-voice/build.gradle
+++ b/bbb-voice/build.gradle
@@ -17,8 +17,14 @@ repositories {
   mavenLocal()
 }
 
+configurations {
+    runtime.exclude group: "org.slf4j", module: "slf4j-api"
+    runtime.exclude group: "org.red5", module: "red5-server"
+    runtime.exclude group: "org.red5", module: "red5-server-common"
+    runtime.exclude group: "org.red5", module: "red5-io"
+}
 
-dependencies {	 
+dependencies {
   // Servlet
   providedCompile 'javax.servlet:servlet-api:2.5@jar'
 
@@ -26,17 +32,18 @@ dependencies {
   providedCompile 'org.apache.mina:mina-core:2.0.17@jar'
   providedCompile 'org.apache.mina:mina-integration-beans:2.0.17@jar'
   providedCompile 'org.apache.mina:mina-integration-jmx:2.0.17@jar'
-	
-  // Spring 
+
+  // Spring
   providedCompile 'org.springframework:spring-web:4.3.12.RELEASE@jar' 
-  providedCompile  'org.springframework:spring-beans:4.3.12.RELEASE@jar'
+  providedCompile 'org.springframework:spring-beans:4.3.12.RELEASE@jar'
   providedCompile 'org.springframework:spring-context:4.3.12.RELEASE@jar'
   providedCompile 'org.springframework:spring-core:4.3.12.RELEASE@jar'
 
+  // Red5
   providedCompile 'org.red5:red5-server:1.0.10-M5@jar'
   providedCompile 'org.red5:red5-server-common:1.0.10-M5@jar'
   providedCompile 'org.red5:red5-io:1.0.10-M5@jar'
-	  
+
   // Logging
   providedCompile 'ch.qos.logback:logback-core:1.2.3@jar'
   providedCompile 'ch.qos.logback:logback-classic:1.2.3@jar'
@@ -49,28 +56,19 @@ dependencies {
   // Otherwise we get exception on aop utils class not found.
   providedCompile 'org.springframework:spring-aop:4.3.12.RELEASE@jar'
   compile 'aopalliance:aopalliance:1.0@jar'
-	
+
   //redis
-  compile 'redis.clients:jedis:2.9.0'
   compile 'org.apache.commons:commons-pool2:2.6.0'
   compile 'com.google.code.gson:gson:2.8.5'
 
-  compile 'org.apache.commons:commons-lang3:3.7'
-  compile 'org.bigbluebutton:bbb-common-message_2.12:0.0.19-SNAPSHOT'
-  
-  // Testing
-  testRuntime 'org.easymock:easymock:3.6@jar'
-}
-
-test {
-    useTestNG()
+  providedCompile 'org.apache.commons:commons-lang3:3.7'
+  compile 'org.bigbluebutton:bbb-common-message_2.12:0.0.20-SNAPSHOT'
 }
 
 war.doLast {
   ant.unzip(src: war.archivePath, dest: "$buildDir/sip")
 }
 
-
 task deploy() << {
 	def red5AppsDir = '/usr/share/red5/webapps'
 	def sipDir = new File("${red5AppsDir}/sip")
@@ -80,5 +78,4 @@ task deploy() << {
 	ant.copy(todir: sipDir) {
     	fileset(dir: "$buildDir/sip")
     }
-} 
-
+}
diff --git a/bbb-voice/deploy.sh b/bbb-voice/deploy.sh
index ebd457e9196547175c1de294c08b6bc833e310c8..b7cab36a4bc4e2ff6e2b72d8bb9bf36079ce3149 100755
--- a/bbb-voice/deploy.sh
+++ b/bbb-voice/deploy.sh
@@ -1,13 +1,10 @@
 #!/bin/bash
 # deploying 'bigbluebutton-apps' to /usr/share/red5/webapps
 
-sudo chmod -R 777 /usr/share/red5/webapps
-sudo chown -R red5.red5 /usr/share/red5/webapps
+sudo chmod -R 777 /usr/share/red5/webapps/*
 
 gradle clean
 gradle resolveDeps
 gradle war deploy
 
-sudo chown -R red5.red5 /usr/share/red5/webapps
-sudo chmod -R 777 /usr/share/red5/webapps
-
+sudo chown -R red5:red5 /usr/share/red5/webapps
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MeetingMessageHandler.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MeetingMessageHandler.java
index 04623357859b93ae1dcb41d49aff0bc66994cbe4..847c837c186a5a48f5639e15a17448169e8134f5 100755
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MeetingMessageHandler.java
+++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MeetingMessageHandler.java
@@ -3,6 +3,8 @@ package org.bigbluebutton.voiceconf.messaging;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
+
+import org.bigbluebutton.common2.redis.pubsub.MessageHandler;
 import org.bigbluebutton.voiceconf.messaging.messages.ValidateConnTokenRespMsg;
 import org.bigbluebutton.voiceconf.red5.ConnectionInvokerService;
 import org.red5.logging.Red5LoggerFactory;
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageDistributor.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageDistributor.java
deleted file mode 100755
index 595bf905cbc5bc84f3f03640c9bf26e6f2e0eda0..0000000000000000000000000000000000000000
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageDistributor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bigbluebutton.voiceconf.messaging;
-
-import java.util.Set;
-
-public class MessageDistributor {
-	private ReceivedMessageHandler handler;
-	private Set<MessageHandler> listeners;
-	
-	public void setMessageListeners(Set<MessageHandler> listeners) {
-		this.listeners = listeners;
-	}
-	
-	public void setMessageHandler(ReceivedMessageHandler handler) {
-		this.handler = handler;
-		if (handler != null) {
-			handler.setMessageDistributor(this);
-		}		
-	}
-	
-	public void notifyListeners(String pattern, String channel, String message) {
-		for (MessageHandler listener : listeners) {
-			listener.handleMessage(pattern, channel, message);
-		}		
-	}	
-}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageReceiver.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageReceiver.java
deleted file mode 100755
index 9033abe06a9a511d90f42520cf8c5daae97b5df6..0000000000000000000000000000000000000000
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageReceiver.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bigbluebutton.voiceconf.messaging;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.JedisPubSub;
-import redis.clients.jedis.exceptions.JedisConnectionException;
-
-public class MessageReceiver {
-	private static Logger log = Red5LoggerFactory.getLogger(MessageReceiver.class, "bigbluebutton");
-
-	private ReceivedMessageHandler handler;
-
-	private Jedis jedis;
-	private volatile boolean receiveMessage = false;
-
-	private final Executor msgReceiverExec = Executors.newSingleThreadExecutor();
-	private final Executor runExec = Executors.newSingleThreadExecutor();
-
-	private final String FROM_BBB_APPS_PATTERN = "from-akka-apps-redis-channel";
-
-	private String host;
-	private int port;
-
-	public void stop() {
-		receiveMessage = false;
-	}
-
-	public void start() {
-		log.info("Ready to receive messages from Redis pubsub.");
-		try {
-			receiveMessage = true;
-			jedis = new Jedis(host, port);
-			// Set the name of this client to be able to distinguish when doing
-			// CLIENT LIST on redis-cli
-			jedis.clientSetname("BbbRed5VoiceSub");
-
-			Runnable messageReceiver = new Runnable() {
-				public void run() {
-					if (receiveMessage) {
-						try {
-							jedis.subscribe(new PubSubListener(), FROM_BBB_APPS_PATTERN);
-						} catch(JedisConnectionException ex) {
-							log.warn("Exception on Jedis connection. Resubscribing to pubsub.");
-							start();
-						} catch (Exception e) {
-							log.error("Error resubscribing to channels: " + e.getMessage());
-						}
-					}
-				}
-			};
-			msgReceiverExec.execute(messageReceiver);
-		} catch (Exception e) {
-			log.error("Error subscribing to channels: " + e.getMessage());
-		}
-	}
-
-	public void setHost(String host){
-		this.host = host;
-	}
-
-	public void setPort(int port) {
-		this.port = port;
-	}
-
-	public void setMessageHandler(ReceivedMessageHandler handler) {
-		this.handler = handler;
-	}
-
-	private class PubSubListener extends JedisPubSub {
-
-		public PubSubListener() {
-			super();
-		}
-
-		@Override
-		public void onMessage(String channel, String message) {
-			// Not used.
-			Runnable task = new Runnable() {
-				public void run() {
-					handler.handleMessage("", channel, message);
-				}
-			};
-
-			runExec.execute(task);
-		}
-
-		@Override
-		public void onPMessage(final String pattern, final String channel, final String message) {
-			System.out.println("RECEIVED onPMessage" + channel + "\n" + message);
-			Runnable task = new Runnable() {
-				public void run() {
-					handler.handleMessage(pattern, channel, message);
-				}
-			};
-
-			runExec.execute(task);
-		}
-
-		@Override
-		public void onPSubscribe(String pattern, int subscribedChannels) {
-			log.debug("Subscribed to the pattern: " + pattern);
-		}
-
-		@Override
-		public void onPUnsubscribe(String pattern, int subscribedChannels) {
-			// Not used.
-		}
-
-		@Override
-		public void onSubscribe(String channel, int subscribedChannels) {
-			// Not used.
-		}
-
-		@Override
-		public void onUnsubscribe(String channel, int subscribedChannels) {
-			// Not used.
-		}
-	}
-}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageSender.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageSender.java
deleted file mode 100755
index 67869c13367f6892a4a7b3e0cf82fcd393844227..0000000000000000000000000000000000000000
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageSender.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bigbluebutton.voiceconf.messaging;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.Protocol;
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
-
-public class MessageSender {
-	private static Logger log = Red5LoggerFactory.getLogger(MessageSender.class, "bigbluebutton");
-
-	private JedisPool redisPool;
-	private volatile boolean sendMessage = false;
-
-	private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
-	private final Executor runExec = Executors.newSingleThreadExecutor();
-	private BlockingQueue<MessageToSend> messages = new LinkedBlockingQueue<MessageToSend>();
-	private String host;
-	private int port;
-
-	public void stop() {
-		sendMessage = false;
-		redisPool.destroy();
-	}
-
-	public void start() {
-
-		GenericObjectPoolConfig config = new GenericObjectPoolConfig();
-		config.setMaxTotal(32);
-		config.setMaxIdle(8);
-		config.setMinIdle(1);
-		config.setTestOnBorrow(true);
-		config.setTestOnReturn(true);
-		config.setTestWhileIdle(true);
-		config.setNumTestsPerEvictionRun(12);
-		config.setMaxWaitMillis(5000);
-		config.setTimeBetweenEvictionRunsMillis(60000);
-		config.setBlockWhenExhausted(true);
-
-		// Set the name of this client to be able to distinguish when doing
-		// CLIENT LIST on redis-cli
-		redisPool = new JedisPool(config, host, port, Protocol.DEFAULT_TIMEOUT, null,
-				Protocol.DEFAULT_DATABASE, "BbbRed5VoicePub");
-
-		log.info("Redis org.bigbluebutton.red5.pubsub.message publisher starting!");
-		try {
-			sendMessage = true;
-
-			Runnable messageSender = new Runnable() {
-				public void run() {
-					while (sendMessage) {
-						try {
-							MessageToSend msg = messages.take();
-							publish(msg.getChannel(), msg.getMessage());
-						} catch (InterruptedException e) {
-							log.warn("Failed to get org.bigbluebutton.red5.pubsub.message from queue.");
-						}
-					}
-				}
-			};
-			msgSenderExec.execute(messageSender);
-		} catch (Exception e) {
-			log.error("Error subscribing to channels: " + e.getMessage());
-		}
-	}
-
-	public void send(String channel, String message) {
-		MessageToSend msg = new MessageToSend(channel, message);
-		messages.add(msg);
-	}
-
-	private void publish(final String channel, final String message) {
-		Runnable task = new Runnable() {
-			public void run() {
-				Jedis jedis = redisPool.getResource();
-				try {
-					jedis.publish(channel, message);
-				} catch(Exception e){
-					log.warn("Cannot publish the org.bigbluebutton.red5.pubsub.message to redis", e);
-				} finally {
-					redisPool.returnResource(jedis);
-				}
-			}
-		};
-
-		runExec.execute(task);
-	}
-
-
-	public void setHost(String host){
-		this.host = host;
-	}
-
-	public void setPort(int port) {
-		this.port = port;
-	}
-}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageToSend.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageToSend.java
deleted file mode 100755
index a72c9c6efe90da652577f9c7de285302abbbe3af..0000000000000000000000000000000000000000
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/MessageToSend.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bigbluebutton.voiceconf.messaging;
-
-public class MessageToSend {
-	private final String channel;
-	private final String message;
-	
-	public MessageToSend(String channel, String message) {
-		this.channel = channel;
-		this.message = message;
-	}
-	
-	public String getChannel() {
-		return channel;
-	}
-	
-	public String getMessage() {
-		return message;
-	}
-}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/ReceivedMessage.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/ReceivedMessage.java
deleted file mode 100755
index 82d14824b11570bb36446b5d29be9977f27ae72f..0000000000000000000000000000000000000000
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/ReceivedMessage.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bigbluebutton.voiceconf.messaging;
-
-public class ReceivedMessage {
-
-	private final String pattern;
-	private final String channel;
-	private final String message;
-	
-	public ReceivedMessage(String pattern, String channel, String message) {
-		this.pattern = pattern;
-		this.channel = channel;
-		this.message = message;
-	}
-
-	public String getPattern() {
-		return pattern;
-	}
-
-	public String getChannel() {
-		return channel;
-	}
-
-	public String getMessage() {
-		return message;
-	}
-	
-
-}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/ReceivedMessageHandler.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/ReceivedMessageHandler.java
deleted file mode 100755
index 596710e10cd61f3cfa0284ef3a85a83b3d6fc7e7..0000000000000000000000000000000000000000
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/ReceivedMessageHandler.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bigbluebutton.voiceconf.messaging;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-
-public class ReceivedMessageHandler {
-	private static Logger log = Red5LoggerFactory.getLogger(ReceivedMessageHandler.class, "bigbluebutton");
-	
-	private BlockingQueue<ReceivedMessage> receivedMessages = new LinkedBlockingQueue<ReceivedMessage>();
-	
-	private volatile boolean processMessage = false;
-	
-	private final Executor msgProcessorExec = Executors.newSingleThreadExecutor();
-	
-	
-	private MessageDistributor handler;
-	
-	public void stop() {
-		processMessage = false;
-	}
-	
-	public void start() {	
-		log.info("Ready to handle messages from Redis pubsub!");
-
-		try {
-			processMessage = true;
-			
-			Runnable messageProcessor = new Runnable() {
-			    public void run() {
-			    	while (processMessage) {
-			    		try {
-							ReceivedMessage msg = receivedMessages.take();
-							processMessage(msg);
-						} catch (InterruptedException e) {
-							log.warn("Error while taking received message from queue.");
-						}   			    		
-			    	}
-			    }
-			};
-			msgProcessorExec.execute(messageProcessor);
-		} catch (Exception e) {
-			log.error("Error subscribing to channels: " + e.getMessage());
-		}			
-	}
-	
-	private void processMessage(ReceivedMessage msg) {
-		if (handler != null) {
-			log.debug("Let's process this message: " + msg.getMessage());
-
-			handler.notifyListeners(msg.getPattern(), msg.getChannel(), msg.getMessage());
-		} else {
-			log.warn("No listeners interested in messages from Redis!");
-		}
-	}
-	
-	public void handleMessage(String pattern, String channel, String message) {
-		ReceivedMessage rm = new ReceivedMessage(pattern, channel, message);
-		receivedMessages.add(rm);
-	}
-	
-	public void setMessageDistributor(MessageDistributor h) {
-		this.handler = h;
-	}
-}
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/RedisMessagingService.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/RedisMessagingService.java
index 11da04a9f7c525a296437691cacb8284b2a82f91..853f5fd4fefc59230ae20d9d00151b3dd210f381 100755
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/RedisMessagingService.java
+++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/messaging/RedisMessagingService.java
@@ -5,6 +5,8 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.bigbluebutton.common2.msgs.*;
+import org.bigbluebutton.common2.redis.pubsub.MessageSender;
+
 import com.google.gson.Gson;
 import org.bigbluebutton.voiceconf.messaging.messages.UserConnectedToGlobalAudio;
 import org.bigbluebutton.voiceconf.messaging.messages.UserDisconnectedFromGlobalAudio;
diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/SipToFlashAudioStream.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/SipToFlashAudioStream.java
index b81cdd554ab63b8384a45994d09b36d6edc0356d..51b77259fb3571d468a49190c72fa62bbba33a56 100644
--- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/SipToFlashAudioStream.java
+++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/SipToFlashAudioStream.java
@@ -19,16 +19,16 @@
 package org.bigbluebutton.voiceconf.red5.media;
 
 import java.net.DatagramSocket;
+
 import org.apache.mina.core.buffer.IoBuffer;
 import org.bigbluebutton.voiceconf.red5.media.transcoder.SipToFlashTranscoder;
 import org.bigbluebutton.voiceconf.red5.media.transcoder.TranscodedAudioDataListener;
 import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.api.IContext;
 import org.red5.server.api.scope.IScope;
-import org.red5.server.net.rtmp.event.AudioData;
+import org.red5.server.net.rtmp.event.AudioData;
 import org.red5.server.net.rtmp.event.Notify;
 import org.red5.server.net.rtmp.message.Constants;
-import org.red5.server.scope.Scope;
 import org.red5.server.stream.IProviderService;
 import org.slf4j.Logger;
 
diff --git a/bbb-voice/src/main/java/org/red5/app/sip/stream/ListenStream.java b/bbb-voice/src/main/java/org/red5/app/sip/stream/ListenStream.java
index e0c4543b911c92fb53ae5e5fd505bf0c120d4fa0..ab41d32d89850cc2861b721fee91411bccd30f7b 100755
--- a/bbb-voice/src/main/java/org/red5/app/sip/stream/ListenStream.java
+++ b/bbb-voice/src/main/java/org/red5/app/sip/stream/ListenStream.java
@@ -5,13 +5,13 @@ import org.red5.app.sip.trancoders.TranscodedAudioDataListener;
 import org.red5.logging.Red5LoggerFactory;
 import org.red5.server.api.IContext;
 import org.red5.server.api.scope.IScope;
-import org.red5.server.net.rtmp.event.AudioData;
+import org.red5.server.net.rtmp.event.AudioData;
 import org.red5.server.scope.Scope;
 import org.red5.server.stream.IProviderService;
 import org.slf4j.Logger;
 
 public class ListenStream implements TranscodedAudioDataListener {
-	final private Logger log = Red5LoggerFactory.getLogger(ListenStream.class, "sip");
+    private final Logger log = Red5LoggerFactory.getLogger(ListenStream.class, "sip");
 		
 	private AudioStream broadcastStream;
 	private IScope scope;
diff --git a/bbb-voice/src/main/webapp/WEB-INF/bbb-redis-messaging.xml b/bbb-voice/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
index fe19d06cc39a355141fc0d48cf604f7b9f8913bb..8da566658471941dd04c309f0028c4ba32835f4b 100755
--- a/bbb-voice/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
+++ b/bbb-voice/src/main/webapp/WEB-INF/bbb-redis-messaging.xml
@@ -24,42 +24,45 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 	xsi:schemaLocation="http://www.springframework.org/schema/beans
 			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 			http://www.springframework.org/schema/util 
-			http://www.springframework.org/schema/util/spring-util-2.0.xsd
-			">
+			http://www.springframework.org/schema/util/spring-util-2.0.xsd">
 	
-	<bean id="messagingService" class="org.bigbluebutton.voiceconf.messaging.RedisMessagingService">
-		<property name="redisMessageSender"> <ref bean="redisMessageSender"/></property>
+	<bean id="redisMessageDistributor" class="org.bigbluebutton.common2.redis.pubsub.MessageDistributor">
+		<property name="messageHandler"> <ref local="redisMessageHandler"/> </property>
+		<property name="messageListeners">
+			<set>
+				<ref bean="meetingMessageHandler" />
+			</set>
+		</property>
+	</bean>
+	
+	<bean id="redisMessageHandler" class="org.bigbluebutton.common2.redis.pubsub.ReceivedMessageHandler"
+		  init-method="start" destroy-method="stop">
+		<property name="messageDistributor"><ref bean="redisMessageDistributor" /></property>
 	</bean>
 
-	<bean id="redisMessageSender" class="org.bigbluebutton.voiceconf.messaging.MessageSender"
+	<bean id="redisMessageSender" class="org.bigbluebutton.common2.redis.pubsub.MessageSender"
 		  init-method="start" destroy-method="stop">
 		<property name="host" value="${redis.host}"/>
 		<property name="port" value="${redis.port}"/>
+		<property name="clientName" value="BbbRed5VoiceSender" />
+		<property name="password" value="${redis.password:}" />
+	</bean>
+	
+	<bean id="messagingService" class="org.bigbluebutton.voiceconf.messaging.RedisMessagingService">
+		<property name="redisMessageSender"> <ref bean="redisMessageSender"/></property>
 	</bean>
 
 	<bean id="meetingMessageHandler" class="org.bigbluebutton.voiceconf.messaging.MeetingMessageHandler">
 		<property name="connInvokerService" ref="connInvokerService"/>
 	</bean>
 
-	<bean id="redisMessageReceiver" class="org.bigbluebutton.voiceconf.messaging.MessageReceiver"
+	<bean id="redisMessageReceiver" class="org.bigbluebutton.common2.redis.pubsub.MessageReceiver"
 		  init-method="start" destroy-method="stop">
 		<property name="host" value="${redis.host}"/>
 		<property name="port" value="${redis.port}"/>
+		<property name="password" value="${redis.password:}" />
+		<property name="clientName" value="BbbRed5VideoReceiver" />
 		<property name="messageHandler"> <ref local="redisMessageHandler"/> </property>
 	</bean>
 
-	<bean id="redisMessageHandler" class="org.bigbluebutton.voiceconf.messaging.ReceivedMessageHandler"
-		  init-method="start" destroy-method="stop">
-		<property name="messageDistributor"><ref bean="redisMessageDistributor" /></property>
-	</bean>
-
-	<bean id="redisMessageDistributor" class="org.bigbluebutton.voiceconf.messaging.MessageDistributor">
-		<property name="messageHandler"> <ref local="redisMessageHandler"/> </property>
-		<property name="messageListeners">
-			<set>
-				<ref bean="meetingMessageHandler" />
-			</set>
-		</property>
-	</bean>
-
 </beans>
diff --git a/bbb-voice/src/main/webapp/WEB-INF/bigbluebutton-sip.properties b/bbb-voice/src/main/webapp/WEB-INF/bigbluebutton-sip.properties
index 370990a1859ac2180df786079036a1d379702eaf..3dc265ff1bea57288d330def75ba2f334fd931fd 100755
--- a/bbb-voice/src/main/webapp/WEB-INF/bigbluebutton-sip.properties
+++ b/bbb-voice/src/main/webapp/WEB-INF/bigbluebutton-sip.properties
@@ -7,7 +7,6 @@ bbb.sip.app.port=5070
 sip.server.username=bbbuser
 sip.server.password=secret
 
-
 # The ip and port of the FreeSWITCH server
 freeswitch.ip=192.168.23.53
 freeswitch.port=5060
@@ -19,8 +18,7 @@ stopAudioPort=16383
 
 redis.host=127.0.0.1
 redis.port=6379
-redis.pass=
-
+redis.password=
 
 # If you want mjsip stack (red5/log/*access*.log) to minimize the amount of logs it
 # generates, set this to a lower value (e.g. 3).
diff --git a/bbb-voice/src/main/webapp/WEB-INF/red5-web.properties b/bbb-voice/src/main/webapp/WEB-INF/red5-web.properties
index 1e17dff094bfb42a2837817c705fdfe500fbb960..5d646d514744049abf439aca1a0e28163e07dc78 100644
--- a/bbb-voice/src/main/webapp/WEB-INF/red5-web.properties
+++ b/bbb-voice/src/main/webapp/WEB-INF/red5-web.properties
@@ -1,2 +1,2 @@
-webapp.contextPath=/sip
-webapp.virtualHosts=*, localhost, localhost:8088, 127.0.0.1:8088
+webapp.contextPath=/sip
+webapp.virtualHosts=*, localhost, localhost:8088, 127.0.0.1:8088
diff --git a/bbb-voice/src/main/webapp/WEB-INF/red5-web.xml b/bbb-voice/src/main/webapp/WEB-INF/red5-web.xml
index 12f3bb8eebe8e7b6c2f0778a9aabf5983d045e08..610836054c018196d4416822c6ab1049a4cd1df7 100755
--- a/bbb-voice/src/main/webapp/WEB-INF/red5-web.xml
+++ b/bbb-voice/src/main/webapp/WEB-INF/red5-web.xml
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-
 <!--
 
 BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
@@ -36,6 +35,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 		</property>
 	</bean>
 	
+	<import resource="bbb-redis-messaging.xml"/>
+	
+	<bean id="clientConnectionManager" class="org.bigbluebutton.voiceconf.red5.ClientConnectionManager"/>
+	
+	<bean id="connInvokerService" class="org.bigbluebutton.voiceconf.red5.ConnectionInvokerService"
+	     init-method="start" destroy-method="stop"/>
 	
 	<bean id="web.context" class="org.red5.server.Context"
 		autowire="byType" />
@@ -49,6 +54,16 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 		<property name="contextPath" value="${webapp.contextPath}" />
 		<property name="virtualHosts" value="${webapp.virtualHosts}" />
 	</bean>
+	
+	<bean id="sipPeerManager" class="org.bigbluebutton.voiceconf.sip.SipPeerManager">
+		<property name="sipStackDebugLevel" value="${sipStackDebugLevel}"/>
+		<property name="sipRemotePort" value="${freeswitch.port}"/>
+		<property name="messagingService" ref="messagingService"/>
+	</bean>
+
+	<bean id="voiceconf.service" class="org.bigbluebutton.voiceconf.red5.Service">
+		<property name="sipPeerManager" ref="sipPeerManager"/>
+	</bean>
 
 	<bean id="web.handler" class="org.bigbluebutton.voiceconf.red5.Application">
 		<property name="sipClientRtpIp" value="${bbb.sip.app.ip}" />
@@ -64,22 +79,4 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 		<property name="messagingService" ref="messagingService"/>
 	</bean>
 
-	<bean id="voiceconf.service" class="org.bigbluebutton.voiceconf.red5.Service">
-		<property name="sipPeerManager" ref="sipPeerManager"/>
-	</bean>
-
-	<bean id="connInvokerService" class="org.bigbluebutton.voiceconf.red5.ConnectionInvokerService"
-		  init-method="start" destroy-method="stop"/>
-
-	<bean id="sipPeerManager" class="org.bigbluebutton.voiceconf.sip.SipPeerManager">
-		<property name="sipStackDebugLevel" value="${sipStackDebugLevel}"/>
-		<property name="sipRemotePort" value="${freeswitch.port}"/>
-		<property name="messagingService" ref="messagingService"/>
-		
-	</bean>
-	
-	<bean id="clientConnectionManager" class="org.bigbluebutton.voiceconf.red5.ClientConnectionManager"/>
-
-	<import resource="bbb-redis-messaging.xml"/>
-
 </beans>
diff --git a/bigbluebutton-apps/build.gradle b/bigbluebutton-apps/build.gradle
index 85dc33cbaf3f8d581abaa6ec6da1cfb687110869..df9dbcd3cf6a98e021ac262074a385a87b31a3ce 100755
--- a/bigbluebutton-apps/build.gradle
+++ b/bigbluebutton-apps/build.gradle
@@ -21,6 +21,13 @@ repositories {
   mavenLocal()
 }
 
+configurations {
+    runtime.exclude group: "org.slf4j", module: "slf4j-api"
+    runtime.exclude group: "org.red5", module: "red5-server"
+    runtime.exclude group: "org.red5", module: "red5-server-common"
+    runtime.exclude group: "org.red5", module: "red5-io"
+}
+
 dependencies {	 
   // Servlet
   providedCompile 'javax.servlet:servlet-api:2.5@jar'
@@ -34,12 +41,13 @@ dependencies {
   providedCompile 'org.springframework:spring-web:4.3.12.RELEASE@jar' 
   providedCompile 'org.springframework:spring-beans:4.3.12.RELEASE@jar'
   providedCompile 'org.springframework:spring-context:4.3.12.RELEASE@jar'
-  providedCompile 'org.springframework:spring-core:4.3.13.RELEASE@jar'
+  providedCompile 'org.springframework:spring-core:4.3.12.RELEASE@jar'
 
   // Red5
   providedCompile 'org.red5:red5-server:1.0.10-M5@jar'
   providedCompile 'org.red5:red5-server-common:1.0.10-M5@jar'
-  
+  providedCompile 'org.red5:red5-io:1.0.10-M5@jar'
+
   // Logging
   providedCompile 'ch.qos.logback:logback-core:1.2.3@jar'
   providedCompile 'ch.qos.logback:logback-classic:1.2.3@jar'
@@ -57,14 +65,13 @@ dependencies {
   compile 'org.easymock:easymock:3.6@jar'
   
   //redis
-  compile "redis.clients:jedis:2.9.0"
   compile 'org.apache.commons:commons-pool2:2.6.0'
  
-   compile 'com.google.code.gson:gson:2.8.5'
-   providedCompile 'org.apache.commons:commons-lang3:3.7'
+  compile 'com.google.code.gson:gson:2.8.5'
+  providedCompile 'org.apache.commons:commons-lang3:3.7'
 
-  compile 'org.bigbluebutton:bbb-common-message_2.12:0.0.19-SNAPSHOT'
-  compile 'org.bigbluebutton:bbb-apps-common_2.12:0.0.3-SNAPSHOT'
+  compile 'org.bigbluebutton:bbb-common-message_2.12:0.0.20-SNAPSHOT'
+  compile 'org.bigbluebutton:bbb-apps-common_2.12:0.0.4-SNAPSHOT'
 }
 
 test {
diff --git a/bigbluebutton-apps/deploy.sh b/bigbluebutton-apps/deploy.sh
index b002c6f858b83aa29961ec5a1b9193b600bbbade..b7cab36a4bc4e2ff6e2b72d8bb9bf36079ce3149 100755
--- a/bigbluebutton-apps/deploy.sh
+++ b/bigbluebutton-apps/deploy.sh
@@ -1,18 +1,10 @@
 #!/bin/bash
 # deploying 'bigbluebutton-apps' to /usr/share/red5/webapps
 
-sudo chown -R red5.red5 /usr/share/red5/webapps
+sudo chmod -R 777 /usr/share/red5/webapps/*
 
 gradle clean
 gradle resolveDeps
 gradle war deploy
 
-sudo chown -R red5.red5 /usr/share/red5/webapps
-
-# Remove slf4j jar as it conflicts with logging with red5
-FILE=/usr/share/red5/webapps/bigbluebutton/WEB-INF/lib/slf4j-api-1.7.25.jar
-if [ -f $FILE ] 
-then
- sudo rm $FILE
-fi
-
+sudo chown -R red5:red5 /usr/share/red5/webapps
diff --git a/bigbluebutton-apps/gradle.properties b/bigbluebutton-apps/gradle.properties
deleted file mode 100644
index a0cdfb5b63d4667c2cdcd67631f5017fd006f34e..0000000000000000000000000000000000000000
--- a/bigbluebutton-apps/gradle.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-## Dependecies Version
-
-# Logging
-log4jVersion = 1.2.17
-slf4jVersion = 1.6.6
-
-# Common libraries
-springVersion = 3.1.4.RELEASE
-springRedisVersion = 1.1.0.RELEASE
-jacksonVersion = 1.8.3
-
-# Testing
-junitVersion = 4.8.1
-mockitoVersion = 1.8.5
-
-
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-redis-pool.xml b/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-redis-pool.xml
deleted file mode 100755
index b72ba93cd2670e60586dec23400a791ac34031de..0000000000000000000000000000000000000000
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-redis-pool.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-
-Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-
-This program is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free Software
-Foundation; either version 3.0 of the License, or (at your option) any later
-version.
-
-BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans
-			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-			http://www.springframework.org/schema/util 
-			http://www.springframework.org/schema/util/spring-util-2.0.xsd
-			">
-  	<!--
-    <bean id="redisPool" class="redis.clients.jedis.JedisPool">
-        <constructor-arg index="0" value="${redis.host}"/>
-        <constructor-arg index="1" value="${redis.port}"/>
-    </bean>
-	    -->
-</beans>
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/classes/application.conf b/bigbluebutton-apps/src/main/webapp/WEB-INF/classes/application.conf
index 74183500ea75522d1927e5742c4f93d2722b1269..3b72838eb4bbe89bb4f2c7d26663b8c90cbd2a2b 100755
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/classes/application.conf
+++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/classes/application.conf
@@ -10,7 +10,7 @@ akka {
   loggers = ["akka.event.slf4j.Slf4jLogger"]
   loglevel = "DEBUG"
 
-  rediscala-publish-worker-dispatcher {
+  redis-publish-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
@@ -18,7 +18,7 @@ akka {
     throughput = 512
   }
 
-  rediscala-subscriber-worker-dispatcher {
+  redis-subscriber-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml b/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml
index 8891ce3b5af9e5a0f53a1552ac80e00323fb2f8d..2023fa50935836d8464329a04c76eee9125187e1 100755
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml
+++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml
@@ -36,7 +36,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
             </property>
     </bean>
 
+    <bean id="msgToClientGW" class="org.bigbluebutton.client.MsgToClientGW" >
+        <constructor-arg index="0" ref="connInvokerService"/>
+    </bean>
+
+    <bean id="clientGWApp" class="org.bigbluebutton.client.ClientGWApplication" destroy-method="shutdown">
+        <constructor-arg index="0" ref="msgToClientGW"/>
+    </bean>
+
     <bean id="web.context" class="org.red5.server.Context" autowire="byType" />
+    
+    <bean id="connInvokerService" class="org.bigbluebutton.red5.client.messaging.ConnectionInvokerService"
+            init-method="start" destroy-method="stop"/>
 
     <bean id="web.scope" class="org.red5.server.scope.WebScope"
          init-method="register">
@@ -47,6 +58,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <property name="contextPath" value="${webapp.contextPath}" />
         <property name="virtualHosts" value="${webapp.virtualHosts}" />
     </bean>
+    
+    <bean id="clientInGW" class="org.bigbluebutton.client.ClientInGW" >
+        <constructor-arg index="0" ref="clientGWApp"/>
+    </bean>
 
     <bean id="web.handler" class="org.bigbluebutton.red5.BigBlueButtonApplication">
         <property name="connInvokerService"><ref bean="connInvokerService"/></property>
@@ -54,25 +69,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <property name="maxMessageLength" value="${maxMessageLength}"/>
     </bean>
 
-    <bean id="clientInGW" class="org.bigbluebutton.client.ClientInGW" >
-        <constructor-arg index="0" ref="clientGWApp"/>
-    </bean>
-
-    <bean id="msgToClientGW" class="org.bigbluebutton.client.MsgToClientGW" >
-        <constructor-arg index="0" ref="connInvokerService"/>
-    </bean>
-
-    <bean id="clientGWApp" class="org.bigbluebutton.client.ClientGWApplication" destroy-method="shutdown">
-        <constructor-arg index="0" ref="msgToClientGW"/>
-    </bean>
-
-    <bean id="connInvokerService" class="org.bigbluebutton.red5.client.messaging.ConnectionInvokerService"
-                init-method="start" destroy-method="stop"/>
-
     <bean id="bbbAppsIsAliveMonitorService" class="org.bigbluebutton.red5.monitoring.BbbAppsIsAliveMonitorService"
                 init-method="start" destroy-method="stop">
         <property name="connectionInvokerService"> <ref bean="connInvokerService"/></property>
     </bean>
-    
-    <import resource="bbb-redis-pool.xml"/>
 </beans>
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/spring/applicationContext-redis.xml b/bigbluebutton-apps/src/main/webapp/WEB-INF/spring/applicationContext-redis.xml
deleted file mode 100755
index ebc657b8c66a89465b13937687f52376c5cc3243..0000000000000000000000000000000000000000
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/spring/applicationContext-redis.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?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:p="http://www.springframework.org/schema/p"
-       xmlns:context="http://www.springframework.org/schema/context" 
-       xsi:schemaLocation="
-            http://www.springframework.org/schema/beans 
-            http://www.springframework.org/schema/beans/spring-beans.xsd
-            http://www.springframework.org/schema/context 
-            http://www.springframework.org/schema/context/spring-context.xsd">
-
-    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
-        p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"/>
-
-    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" 
-        p:connection-factory-ref="connectionFactory"/>
-    
-</beans>
diff --git a/bigbluebutton-web/build.gradle b/bigbluebutton-web/build.gradle
index e896556837ac125afde499b1e96e1196d07edd4c..1da581703e573a0f15b9a7c83bedd670346f009f 100755
--- a/bigbluebutton-web/build.gradle
+++ b/bigbluebutton-web/build.gradle
@@ -2,9 +2,9 @@ apply plugin: 'java'
 apply plugin: 'eclipse'
 
 task resolveDeps(type: Copy) {
-    into('lib')
-    from configurations.default
-    from configurations.default.allArtifacts.file
+  into('lib')
+  from configurations.default
+  from configurations.default.allArtifacts.file
 }
 
 repositories {
@@ -12,41 +12,34 @@ repositories {
   mavenLocal()
 }
 
+configurations {
+    runtime.exclude group: "org.slf4j", module: "slf4j-api"
+    compile.exclude group: "org.red5", module: "red5-server-common"
+}
+  
 dependencies {
-	compile 'org.bigbluebutton:bbb-common-web:0.0.2-SNAPSHOT'
-
+  compile 'org.bigbluebutton:bbb-common-web:0.0.3-SNAPSHOT'
 
   // XML creation speedup
   compile 'org.freemarker:freemarker:2.3.28'
 
-	//junit
-	compile 'junit:junit:4.8.2'
+  //junit
+  testCompile 'junit:junit:4.12'
 
-	// Testing
-	testCompile 'org.testng:testng:5.8@jar'
-	testCompile 'org.easymock:easymock:2.4@jar'
+  // Testing
+  testCompile 'org.testng:testng:6.14.3@jar'
+  testCompile 'org.easymock:easymock:4.0.1@jar'
 }
 
 sourceSets {
-	main {
-			java {
-					srcDir 'src/java'
-			}
-			resources {
-					srcDir 'src/resources'
-			}
-	}
-	test {
-		java {
-				srcDir 'test/unit'
-		}
-		resources {
-				srcDir 'test/resources'
-		}
-}
-}
-
-test {
-	useTestNG()
+  main {
+    java { srcDir 'src/java' }
+    resources { srcDir 'src/resources' }
+  }
+  test {
+    java { srcDir 'test/unit' }
+    resources { srcDir 'test/resources' }
+  }
 }
 
+test { useTestNG() }
diff --git a/bigbluebutton-web/build.sh b/bigbluebutton-web/build.sh
index f725095d2b29cef1098d538598406c12e3a0aff8..a18f016ad30ffbe69eec5c567c0a45f69920c398 100755
--- a/bigbluebutton-web/build.sh
+++ b/bigbluebutton-web/build.sh
@@ -1,4 +1,3 @@
 gradle clean
 gradle resolveDeps
 grails clean
-
diff --git a/bigbluebutton-web/grails-app/conf/application.conf b/bigbluebutton-web/grails-app/conf/application.conf
index f5ba5981ea95dd5f9aa8871e4a5e9b524822df44..c6fc978954d01f9506e65f33ab525eb6dbbe82c3 100644
--- a/bigbluebutton-web/grails-app/conf/application.conf
+++ b/bigbluebutton-web/grails-app/conf/application.conf
@@ -10,7 +10,7 @@ akka {
   loggers = ["akka.event.slf4j.Slf4jLogger"]
   loglevel = "DEBUG"
 
-  rediscala-publish-worker-dispatcher {
+  redis-publish-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
@@ -18,7 +18,7 @@ akka {
     throughput = 512
   }
 
-  rediscala-subscriber-worker-dispatcher {
+  redis-subscriber-worker-dispatcher {
     mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
     # Throughput defines the maximum number of messages to be
     # processed per actor before the thread jumps to the next actor.
diff --git a/bigbluebutton-web/grails-app/conf/spring/bbb-redis-messaging.xml b/bigbluebutton-web/grails-app/conf/spring/bbb-redis-messaging.xml
index 3c8c2765b3a45a1703d8b3ef705fd6d3b52a4ba6..4c95196bdb63128883c2d7732e8b2467dd547699 100755
--- a/bigbluebutton-web/grails-app/conf/spring/bbb-redis-messaging.xml
+++ b/bigbluebutton-web/grails-app/conf/spring/bbb-redis-messaging.xml
@@ -3,7 +3,7 @@
 
 BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
 
-Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
 
 This program is free software; you can redistribute it and/or modify it under the
 terms of the GNU Lesser General Public License as published by the Free Software
@@ -19,14 +19,38 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 
 -->
 <beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:util="http://www.springframework.org/schema/util"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
 			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 			http://www.springframework.org/schema/util 
 			http://www.springframework.org/schema/util/spring-util-2.0.xsd
 			">
 
-
-
+	<bean id="redisStorageService"
+		class="org.bigbluebutton.common2.redis.RedisStorageService"
+		init-method="start" destroy-method="stop">
+		<property name="host" value="${redisHost}" />
+		<property name="port" value="${redisPort}" />
+		<property name="password" value="${redisPassword:}" />
+		<property name="clientName" value="BbbWeb" />
+	</bean>
+
+	<bean id="redisMessageHandler"
+		class="org.bigbluebutton.api.messaging.ReceivedMessageHandler"
+		init-method="start" destroy-method="stop">
+	</bean>
+
+	<bean id="redisMessageDistributor"
+		class="org.bigbluebutton.api.messaging.MessageDistributor">
+		<property name="messageHandler">
+			<ref local="redisMessageHandler" />
+		</property>
+		<property name="messageListeners">
+			<set>
+				<ref bean="meetingService" />
+				<ref bean="keepAliveService" />
+			</set>
+		</property>
+	</bean>
 </beans>
diff --git a/bigbluebutton-web/grails-app/conf/spring/bbb-redis-pool.xml b/bigbluebutton-web/grails-app/conf/spring/bbb-redis-pool.xml
deleted file mode 100755
index 7de4b5722c6c893f3b0e1a700523af21c34a7624..0000000000000000000000000000000000000000
--- a/bigbluebutton-web/grails-app/conf/spring/bbb-redis-pool.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-
-Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-
-This program is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free Software
-Foundation; either version 3.0 of the License, or (at your option) any later
-version.
-
-BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans
-			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-			http://www.springframework.org/schema/util 
-			http://www.springframework.org/schema/util/spring-util-2.0.xsd
-			">
-  	
-
-    
-</beans>
diff --git a/bigbluebutton-web/grails-app/conf/spring/resources.xml b/bigbluebutton-web/grails-app/conf/spring/resources.xml
index 098e37e48cc009e85761c5ae90804a1ee2b029fa..7a94317cf177761d6f872050d147997241495779 100755
--- a/bigbluebutton-web/grails-app/conf/spring/resources.xml
+++ b/bigbluebutton-web/grails-app/conf/spring/resources.xml
@@ -61,28 +61,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <constructor-arg index="3" value="${screenshareConfSuffix}"/>
     </bean>
 
-    <bean id="redisStorageService" class="org.bigbluebutton.api.messaging.RedisStorageService"
-          init-method="start" destroy-method="stop">
-        <property name="host" value="${redisHost}"/>
-        <property name="port" value="${redisPort}"/>
-    </bean>
-
-
-    <bean id="redisMessageHandler" class="org.bigbluebutton.api.messaging.ReceivedMessageHandler"
-          init-method="start" destroy-method="stop">
-    </bean>
-
-
-    <bean id="redisMessageDistributor" class="org.bigbluebutton.api.messaging.MessageDistributor">
-        <property name="messageHandler"> <ref local="redisMessageHandler"/> </property>
-        <property name="messageListeners">
-            <set>
-                <ref bean="meetingService" />
-                <ref bean="keepAliveService" />
-            </set>
-        </property>
-    </bean>
-
     <bean id="recordingServiceHelper" class="org.bigbluebutton.api.util.RecordingMetadataReaderHelper">
         <property name="recordingServiceGW" ref="recordingServiceGW"/>
     </bean>
@@ -154,9 +132,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
     </bean>
 
     <import resource="doc-conversion.xml"/>
-    <import resource="bbb-redis-pool.xml"/>
-    <!--
     <import resource="bbb-redis-messaging.xml"/>
-    -->
     <import resource="turn-stun-servers.xml"/>
 </beans>
diff --git a/bigbluebutton-web/pres-checker/build.gradle b/bigbluebutton-web/pres-checker/build.gradle
index c918e988075707c2972cfe7f36fa80d37387e134..dfb9bee22f6f85534f9c9599f99f119a7dd6fac8 100755
--- a/bigbluebutton-web/pres-checker/build.gradle
+++ b/bigbluebutton-web/pres-checker/build.gradle
@@ -1,15 +1,15 @@
 apply plugin: 'java'
 
-sourceCompatibility=1.8
-targetCompatibility=1.8
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
 
 version = '0.0.1'
-archivesBaseName = 'bbb-pres-check' 
+archivesBaseName = 'bbb-pres-check'
 
 task resolveDeps(type: Copy) {
-    into('lib')
-    from configurations.default
-    from configurations.default.allArtifacts.file
+  into('lib')
+  from configurations.default
+  from configurations.default.allArtifacts.file
 }
 
 repositories {
@@ -17,22 +17,21 @@ repositories {
   mavenLocal()
 }
 
-dependencies {	   
-   compile 'org.apache.poi:poi:3.17@jar'  
-   compile 'org.apache.poi:poi-ooxml:3.17@jar'
-   compile 'org.apache.poi:poi-ooxml-schemas:3.17@jar'
-   compile 'commons-io:commons-io:2.6@jar'
-   compile 'org.apache.commons:commons-lang3:3.7@jar'
-   compile 'org.apache.commons:commons-collections4:4.2@jar'
-   compile 'org.apache.xmlbeans:xmlbeans:3.0.0@jar'
+dependencies {
+  compile 'org.apache.poi:poi:4.0.0@jar'
+  compile 'org.apache.poi:poi-ooxml:4.0.0@jar'
+  compile 'org.apache.poi:poi-ooxml-schemas:4.0.0@jar'
+  compile 'commons-io:commons-io:2.6@jar'
+  compile 'org.apache.commons:commons-lang3:3.8.1@jar'
+  compile 'org.apache.commons:commons-collections4:4.2@jar'
+  compile 'org.apache.xmlbeans:xmlbeans:3.0.2@jar'
 }
 
 jar {
-   manifest.mainAttributes("Permissions": "all-permissions")
-   manifest.mainAttributes("Codebase": "*")
-   manifest.mainAttributes("Application-Name": "BigBlueButton Presentation Checker")
-   manifest.mainAttributes("Application-Library-Allowable-Codebase": "*")
-   manifest.mainAttributes("Caller-Allowable-Codebase": "*")
-   manifest.mainAttributes("Trusted-Only": "true")
+  manifest.mainAttributes("Permissions": "all-permissions")
+  manifest.mainAttributes("Codebase": "*")
+  manifest.mainAttributes("Application-Name": "BigBlueButton Presentation Checker")
+  manifest.mainAttributes("Application-Library-Allowable-Codebase": "*")
+  manifest.mainAttributes("Caller-Allowable-Codebase": "*")
+  manifest.mainAttributes("Trusted-Only": "true")
 }
-
diff --git a/bigbluebutton-web/pres-checker/build.sh b/bigbluebutton-web/pres-checker/build.sh
index 1f5048f55723f9d76bfbb4b1bcf08e307fe7069d..d2a60ea6951cb7b6607e066cc3ff1812419a0927 100755
--- a/bigbluebutton-web/pres-checker/build.sh
+++ b/bigbluebutton-web/pres-checker/build.sh
@@ -1,4 +1,3 @@
 gradle clean
 gradle jar
 cp build/lib/*.jar lib
-
diff --git a/bigbluebutton-web/pres-checker/run.sh b/bigbluebutton-web/pres-checker/run.sh
index 04fc97183cb1bc79fd22dc6a6f395865a4409bbe..faa48086ab4fed3f2534705e3ab0de49af682724 100755
--- a/bigbluebutton-web/pres-checker/run.sh
+++ b/bigbluebutton-web/pres-checker/run.sh
@@ -1,2 +1 @@
 java -cp "/usr/share/prescheck/lib/*" org.bigbluebutton.prescheck.Main $@
-
diff --git a/bigbluebutton-web/run.sh b/bigbluebutton-web/run.sh
index b707bed78f2b5e48049e3430bfb67c6257aa8658..a9e681a95cbf97223c494f7ad14b2f170cb7eee4 100755
--- a/bigbluebutton-web/run.sh
+++ b/bigbluebutton-web/run.sh
@@ -1,2 +1 @@
 grails -Dserver.port=8989 run-war
-
diff --git a/bigbluebutton-web/test/unit/org/bigbluebutton/api/messaging/NullMessagingService.java b/bigbluebutton-web/test/unit/org/bigbluebutton/api/messaging/NullMessagingService.java
index 8c12f4d2d9130c88bef4b42509c1ecfbbeb75e9e..03ee0fdfa0775e25b3714557aa7fc41926babd2e 100644
--- a/bigbluebutton-web/test/unit/org/bigbluebutton/api/messaging/NullMessagingService.java
+++ b/bigbluebutton-web/test/unit/org/bigbluebutton/api/messaging/NullMessagingService.java
@@ -5,79 +5,65 @@ import java.util.Map;
 
 public class NullMessagingService implements MessagingService {
 
-	public void start() {
-		// TODO Auto-generated method stub
+    public void start() {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
-	public void stop() {
-		// TODO Auto-generated method stub
+    public void stop() {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
-	@Override
-	public void recordMeetingInfo(String meetingId, Map<String, String> info) {
-		// TODO Auto-generated method stub
+    @Override
+    public void recordMeetingInfo(String meetingId, Map<String, String> info) {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
-	/*@Override
-	public void recordMeetingMetadata(String meetingId,
-			Map<String, String> metadata) {
-		// TODO Auto-generated method stub
+    /*
+     * @Override public void recordMeetingMetadata(String meetingId, Map<String,
+     * String> metadata) { // TODO Auto-generated method stub
+     * 
+     * }
+     */
 
-	}*/
+    public void addListener(MessageListener listener) {
+        // TODO Auto-generated method stub
 
-	@Override
-	public void endMeeting(String meetingId) {
-		// TODO Auto-generated method stub
+    }
 
-	}
+    public void removeListener(MessageListener listener) {
+        // TODO Auto-generated method stub
 
-	@Override
-	public void send(String channel, String message) {
-		// TODO Auto-generated method stub
+    }
 
-	}
+    public void destroyMeeting(String meetingID) {
+        // TODO Auto-generated method stub
 
-	public void addListener(MessageListener listener) {
-		// TODO Auto-generated method stub
+    }
 
-	}
+    public void createMeeting(String meetingID, String externalMeetingID, String meetingName, Boolean recorded,
+            String voiceBridge, Long duration) {
+        // TODO Auto-generated method stub
 
-	public void removeListener(MessageListener listener) {
-		// TODO Auto-generated method stub
+    }
 
-	}
+    public void sendPolls(String meetingId, String title, String question, String questionType, List<String> answers) {
+        // TODO Auto-generated method stub
 
-  public void destroyMeeting(String meetingID) {
-	  // TODO Auto-generated method stub
-	  
-  }
+    }
 
-  public void createMeeting(String meetingID, String externalMeetingID, String meetingName,
-      Boolean recorded, String voiceBridge, Long duration) {
-	  // TODO Auto-generated method stub
-	  
-  }
+    @Override
+    public void recordBreakoutInfo(String meetingId, Map<String, String> breakoutInfo) {
+        // TODO Auto-generated method stub
 
-  public void sendPolls(String meetingId, String title, String question,
-      String questionType, List<String> answers) {
-	  // TODO Auto-generated method stub
-	  
-  }
+    }
 
-	@Override
-  public void registerUser(String meetingID, String internalUserId,
-      String fullname, String role, String externUserID, String authToken, String avatarURL) {
-	  // TODO Auto-generated method stub
-	  
-  }
+    @Override
+    public void addBreakoutRoom(String parentId, String breakoutId) {
+        // TODO Auto-generated method stub
 
-	@Override
-  public void sendKeepAlive(String keepAliveId) {
-	  // TODO Auto-generated method stub
-	  
-  }
+    }
 
 }