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

se.jguru.shared.messaging.test.jms.artemis.ArtemisTestClient.kt Maven / Gradle / Ivy

/*-
 * #%L
 * Nazgul Project: jguru-shared-messaging-jms-test
 * %%
 * Copyright (C) 2018 - 2023 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 * 
 * You may obtain a copy of the License at
 * 
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 * 
 * 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.
 * #L%
 */
package se.jguru.shared.messaging.test.jms.artemis

import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
import org.apache.activemq.artemis.jms.client.ActiveMQDestination
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import jakarta.jms.BytesMessage
import jakarta.jms.Connection
import jakarta.jms.ConnectionFactory
import jakarta.jms.JMSException
import jakarta.jms.MapMessage
import jakarta.jms.Message
import jakarta.jms.MessageProducer
import jakarta.jms.ObjectMessage
import jakarta.jms.Session
import jakarta.jms.StreamMessage
import jakarta.jms.TextMessage

private val log: Logger = LoggerFactory.getLogger(ArtemisTestClient::class.java)

/**
 * Simple client implementation which can be used to talk to an Artemis Broker in unit test scope.
 *
 * @param vmURL The URL used by the [ActiveMQConnectionFactory], such as "vm://0" or "tcp://localhost:61616".
 *
 * @author [Lennart Jörelid](mailto:[email protected]), jGuru Europe AB
 */
open class ArtemisTestClient @JvmOverloads constructor(vmURL: String, transactedSession: Boolean = false) {

  var connectionFactory: ConnectionFactory = ActiveMQConnectionFactory(vmURL)
  var connection: Connection?
  var session: Session?
  var producer: MessageProducer?

  init {
    try {

      connection = connectionFactory.createConnection()
      session = when (transactedSession) {
        false -> connection!!.createSession()
        else -> connection!!.createSession(true, Session.AUTO_ACKNOWLEDGE)
      }
      producer = session!!.createProducer(null)
      connection!!.start()

    } catch (jmsEx: JMSException) {
      throw IllegalStateException("InternalClient creation failure", jmsEx)
    }
  }

  /**
   * Shuts down the MessageProducer, Session and Connection.
   */
  fun stop() {
    try {
      producer!!.close()
    } catch (jmsEx: JMSException) {
      log.warn("JMSException encounter closing InternalClient Session - MessageProducer", jmsEx)
    } finally {
      producer = null
    }

    try {
      session!!.close()
    } catch (jmsEx: JMSException) {
      log.warn("JMSException encounter closing InternalClient Session - ignoring", jmsEx)
    } finally {
      session = null
    }

    if (null != connection) {
      try {
        connection!!.close()
      } catch (jmsEx: JMSException) {
        log.warn("JMSException encounter closing InternalClient Connection - ignoring", jmsEx)
      } finally {
        connection = null
      }
    }
  }

  /**
   * Creates a BytesMessage without any body.
   */
  fun createBytesMessage(): BytesMessage {
    checkSession()

    try {
      return session!!.createBytesMessage()
    } catch (jmsEx: JMSException) {
      throw IllegalStateException("Failed to create BytesMessage", jmsEx)
    }

  }

  @Suppress("KotlinConstantConditions")
  fun  createEmptyMessage(typeToCreate: Class): T {

    checkSession()

    val permittedTypes = arrayOf(TextMessage::class.java,
                                 MapMessage::class.java,
                                 ObjectMessage::class.java,
                                 BytesMessage::class.java,
                                 StreamMessage::class.java)

    val theSession = session!!

    return when (typeToCreate) {
      is TextMessage -> theSession.createTextMessage()
      is MapMessage -> theSession.createMapMessage()
      is ObjectMessage -> theSession.createObjectMessage()
      is BytesMessage -> theSession.createBytesMessage()
      is StreamMessage -> theSession.createStreamMessage()
      else -> {

        val okTypes = permittedTypes
          .map { it.name }
          .reduce { acc, s -> "$acc, $s" }

        throw IllegalArgumentException("Cannot create a JMS message of type [${typeToCreate::class.java.name}." +
                                         "Permitted types: $okTypes")
      }
    } as T
  }

  fun createTextMessage(): TextMessage {
    checkSession()

    try {
      return session!!.createTextMessage()
    } catch (jmsEx: JMSException) {
      throw IllegalStateException("Failed to create TextMessage", jmsEx)
    }

  }

  fun createMapMessage(): MapMessage {
    checkSession()

    try {
      return session!!.createMapMessage()
    } catch (jmsEx: JMSException) {
      throw IllegalStateException("Failed to create MapMessage", jmsEx)
    }

  }

  fun createObjectMessage(): ObjectMessage {
    checkSession()

    try {
      return session!!.createObjectMessage()
    } catch (jmsEx: JMSException) {
      throw IllegalStateException("Failed to create ObjectMessage", jmsEx)
    }

  }

  fun createStreamMessage(): StreamMessage {
    checkSession()
    try {
      return session!!.createStreamMessage()
    } catch (jmsEx: JMSException) {
      throw IllegalStateException("Failed to create StreamMessage", jmsEx)
    }

  }

  @JvmOverloads
  fun pushMessage(destination: ActiveMQDestination, message: Message, commitSession: Boolean = true) {
    if (producer == null) {
      throw IllegalStateException("JMS MessageProducer is null - has the InternalClient been started?")
    }

    try {
      producer!!.send(destination, message)
    } catch (jmsEx: JMSException) {
      throw IllegalStateException("Failed to push ${message::class.java.simpleName} to $destination.", jmsEx)
    }

    if (session != null && session!!.transacted && commitSession) {
      try {
        session!!.commit()
      } catch (e: Exception) {
        throw IllegalStateException("Failed to commit JMS Session", e)
      }
    }
  }

  private fun checkSession() {
    if (session == null) {
      throw IllegalStateException("JMS Session is null - has the InternalClient been started?")
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy