All Downloads are FREE. Search and download functionalities are using the official Maven repository.

blended.itestsupport.jms.JMSConnectorActor.scala Maven / Gradle / Ivy

/*
 * Copyright 2014ff,  https://github.com/woq-blended
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package blended.itestsupport.jms

import javax.jms.{Connection, ConnectionFactory}

import akka.actor.{Actor, ActorLogging, Props}
import blended.itestsupport.jms.protocol._

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

object JMSConnectorActor {
  def apply(cf: ConnectionFactory) = new JMSConnectorActor(cf)
}

class JMSConnectorActor(cf: ConnectionFactory) extends Actor with ActorLogging {

  implicit val ctxt = context.dispatcher
  var postStopActions = List.empty[() => Unit]

  private def addPostStopAction(f : () => Unit) : Unit = {
    postStopActions = f :: postStopActions
  }

  private def clearPostStopActions() : Unit = {
    postStopActions = List.empty[() => Unit]
  }

  def receive = disconnected

  def disconnected : Receive = {
    case Connect(clientId, user, pwd) => {
      val result = try {
        Await.result(createConnection(clientId, user, pwd), 1.second)
      } catch {
        case t: Throwable => Left(JMSCaughtException(t))
      }

      sender ! result
    }
  }

  def connected(connection: Connection) : Receive =  {
    case Disconnect => {
      connection.close()
      context.become(disconnected)
      clearPostStopActions()
      sender ! Right(Disconnected)
    }
    case CreateProducer(destName, msgCounter) => {
      log.info(s"Creating a producer for [${destName}] with clientId [${connection.getClientID}]")
      val producer = context.actorOf(Props(Producer(connection, destName, msgCounter)))
      sender ! ProducerActor(producer)
    }
    case CreateConsumer(destName, msgCounter) => {
      log.info(s"Creating a consumer for [${destName}] with clientId [${connection.getClientID}]")
      val consumer = context.actorOf(Props(Consumer(connection, destName, None, msgCounter)))
      consumer.forward(Consumer.ConsumerCreated)
    }
    case CreateDurableSubscriber(destName,subscriberName,msgCounter) => {
      log.info(s"Creating a durable subscriber for [${destName}] with clientId [${connection.getClientID}] and subscriberName")
      val consumer = context.actorOf(Props(Consumer(connection, destName, Some(subscriberName), msgCounter)))
      consumer.forward(Consumer.ConsumerCreated)
    }
  }

  override def postStop(): Unit = {

    postStopActions.foreach(f => f)
    clearPostStopActions()
    super.postStop()
  }

  private def createConnection(
    clientId: String, user: Option[String], password: Option[String]
  ) : Future[Either[JMSCaughtException, Connected]] = {

    Future {
      try {
        val connection = if (user.isDefined && password.isDefined)
          cf.createConnection(user.get, password.get)
        else
          cf.createConnection()

        log.debug(s"Connection [${clientId}] created ...")

        connection.setClientID(clientId)
        connection.start()
        context.become(connected(connection))

        val f = (() => { c: Connection =>
          log.debug(s"Closing connection [${clientId}]")
          c.close()
        }.apply(connection))

        addPostStopAction(f)

        Right(Connected(clientId))
      } catch {
        case t: Throwable =>
          log.debug(s"Couldn't create JMS connection [${clientId}]")
          Left(JMSCaughtException(t))
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy