JMS

DSL for JMS

JMS support was initially contributed by Jason Koch.

Prerequisites

Gatling JMS DSL is not imported by default.

You have to manually add the following imports:

     
import javax.jms.*;
import io.gatling.javaapi.jms.*;

import static io.gatling.javaapi.jms.JmsDsl.*;
import javax.jms.*
import io.gatling.javaapi.jms.*
import io.gatling.javaapi.jms.JmsDsl.*
import javax.jms._
import io.gatling.jms.Predef._

JMS protocol

Use the jms object in order to create a JMS protocol.

connectionFactory

The first mandatory step is to configure the ConnectionFactory.

You can either configure one to be retrieved with a JNDI lookup:

     
JmsJndiConnectionFactoryBuilder jndiBasedConnectionFactory = jmsJndiConnectionFactory
  .connectionFactoryName("ConnectionFactory")
  .url("tcp://localhost:61616")
  // optional, for performing JNDI lookup
  .credentials("username", "password")
  // optional, custom JNDI property
  .property("foo", "bar")
  .contextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory");

JmsProtocolBuilder jmsProtocol = jms
  .connectionFactory(jndiBasedConnectionFactory);
val jndiBasedConnectionFactory = jmsJndiConnectionFactory
  .connectionFactoryName("ConnectionFactory")
  .url("tcp://localhost:61616")
  // optional, for performing JNDI lookup
  .credentials("username", "password")
  // optional, custom JNDI property
  .property("foo", "bar")
  .contextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory")

val jmsProtocol = jms
  .connectionFactory(jndiBasedConnectionFactory)
val jndiBasedConnectionFactory = jmsJndiConnectionFactory
  .connectionFactoryName("ConnectionFactory")
  .url("tcp://localhost:61616")
  // optional, for performing JNDI lookup
  .credentials("username", "password")
  // optional, custom JNDI property
  .property("foo", "bar")
  .contextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory")

val jmsProtocol = jms
  .connectionFactory(jndiBasedConnectionFactory)

or directly instantiate one with your JMS broker’s Java client library, eg:

     
ConnectionFactory connectionFactory =
  new org.apache.activemq.ActiveMQConnectionFactory("url");

JmsProtocolBuilder jmsProtocol = jms
  .connectionFactory(connectionFactory);
val connectionFactory: ConnectionFactory =
  org.apache.activemq.ActiveMQConnectionFactory("url")

val jmsProtocol = jms
  .connectionFactory(connectionFactory)
val connectionFactory =
  new org.apache.activemq.ActiveMQConnectionFactory("url")

val jmsProtocol = jms
  .connectionFactory(connectionFactory)

Other options

     
jms
  .connectionFactory(connectionFactory)
  .credentials("username", "password")
  // optional, default to non persistent
  .useNonPersistentDeliveryMode()
  .useNonPersistentDeliveryMode()

  // optional, default to 1
  // listener thread count
  // some JMS implementation (like IBM MQ) need more than one MessageListener
  // to achieve full readout performance
  .listenerThreadCount(5)

  // optional, default to `matchByMessageId`
  // specify how request and response messages should be matched when using `requestReply`
  // Use `matchByCorrelationId` for ActiveMQ.
  .matchByCorrelationId()
  .matchByMessageId()
  // use a custom matching strategy
  .messageMatcher((io.gatling.javaapi.jms.JmsMessageMatcher) null)

  // optional, default to none
  .replyTimeout(1000);
jms
  .connectionFactory(connectionFactory)
  .credentials("username", "password")
  // optional, default to non persistent
  .useNonPersistentDeliveryMode()
  .useNonPersistentDeliveryMode()

  // optional, default to 1
  // listener thread count
  // some JMS implementation (like IBM MQ) need more than one MessageListener
  // to achieve full readout performance
  .listenerThreadCount(5)

  // optional, default to `matchByMessageId`
  // specify how request and response messages should be matched when using `requestReply`
  // Use `matchByCorrelationId` for ActiveMQ.
  .matchByCorrelationId()
  .matchByMessageId() // use a custom matching strategy
  // see io.gatling.javaapi.jms.JmsMessageMatcher
  .messageMatcher(null as io.gatling.javaapi.jms.JmsMessageMatcher)

  // optional, default to none
  .replyTimeout(1000)
jms
  .connectionFactory(connectionFactory)
  .credentials("username", "password")
  // optional, default to non persistent
  .useNonPersistentDeliveryMode
  .useNonPersistentDeliveryMode

  // optional, default to 1
  // listener thread count
  // some JMS implementation (like IBM MQ) need more than one MessageListener
  // to achieve full readout performance
  .listenerThreadCount(5)

  // optional, default to `matchByMessageId`
  // specify how request and response messages should be matched
  // Use `matchByCorrelationId` for ActiveMQ.
  .matchByCorrelationId
  .matchByMessageId
  // use a custom matching strategy
  .messageMatcher(null.asInstanceOf[io.gatling.jms.protocol.JmsMessageMatcher])

  // optional, default to none
  .replyTimeout(1000)

JMS request

Use the jms("requestName") method in order to create a JMS request.

Request type

Currently, requestReply and send (fire and forget) requests are supported.

Destination

Define the target destination with queue("queueName") or alternatively with destination(JmsDestination).

Optionally, you can define a reply destination with replyQueue("responseQueue") or replyDestination(JmsDestination). Otherwise, Gatling will use a dynamic queue.

If you do so, you have the possibility of not setting the JMSReplyTo header with noJmsReplyTo.

Additionally, for the reply destination, you can define a JMS selector with selector

If you have the need to measure the time when a message arrive at a message queue different from the replyDestination(JmsDestination), you can additionally define a trackerDestination(JmsDestination).

Message

  • textMessage
  • bytesMessage
  • mapMessage
  • objectMessage for java.io.Serializable payloads

See below for a few examples:

     
// with a static text message
jms("name").send().queue("queueName")
  .textMessage("message");
// with a Gatling EL string text message
jms("name").send().queue("queueName")
  .textMessage("#{message}");
// with a function text message
jms("name").send().queue("queueName")
  .textMessage(session -> session.getString("message"));
// with a ElFileBody template text message
jms("name").send().queue("queueName")
  .textMessage(ElFileBody("templatePath"));

// with a static bytes message
jms("name").send().queue("queueName")
  .bytesMessage(new byte[] { 0, 1, 2 });
// with a RawFileBody bytes message
jms("name").send().queue("queueName")
  .bytesMessage(RawFileBody("templatePath"));
// with a static text message
jms("name").send().queue("queueName")
  .textMessage("message")
// with a Gatling EL string text message
jms("name").send().queue("queueName")
  .textMessage("#{message}")
// with a function text message
jms("name").send().queue("queueName")
  .textMessage { session -> session.getString("message") }
// with a ElFileBody template text message
jms("name").send().queue("queueName")
  .textMessage(ElFileBody("templatePath"))

// with a static bytes message
jms("name").send().queue("queueName")
  .bytesMessage(byteArrayOf(0, 1, 2))
// with a RawFileBody bytes message
jms("name").send().queue("queueName")
  .bytesMessage(RawFileBody("templatePath"))
// with a static text message
jms("name").send.queue("queueName")
  .textMessage("message")
// with a Gatling EL string text message
jms("name").send.queue("queueName")
  .textMessage("#{message}")
// with a function text message
jms("name").send.queue("queueName")
  .textMessage(session => session("message").as[String])
// with a ElFileBody template text message
jms("name").send.queue("queueName")
  .textMessage(ElFileBody("templatePath"))

// with a static bytes message
jms("name").send.queue("queueName")
  .bytesMessage(Array[Byte](0, 1, 2))
// with a RawFileBody bytes message
jms("name").send.queue("queueName")
  .bytesMessage(RawFileBody("templatePath"))

Extra options

  • jmsType
  • property
     
jms("name").send().queue("queueName")
  .textMessage("message")
  .jmsType("type")
  .property("foo", "bar");
jms("name").send().queue("queueName")
  .textMessage("message")
  .jmsType("type")
  .property("foo", "bar")
jms("name").send.queue("queueName")
  .textMessage("message")
  .jmsType("type")
  .property("foo", "bar")

JMS check

Gatling JMS’s support only current supports the following checks:

It also supports jmsProperty for checking JMS properties on reply messages.

     
jms("name").requestReply().queue("queueName")
  .textMessage("message")
  // check a String property
  .check(jmsProperty("foo").is("bar"))
  // check an int property
  .check(jmsProperty("foo").ofInt().is(1))
  // save a property
  .check(jmsProperty("foo").saveAs("fooProperty"));
jms("name").requestReply().queue("queueName")
  .textMessage("message")
  // check a String property
  .check(jmsProperty("foo").shouldBe("bar"))
  // check an int property
  .check(jmsProperty("foo").ofInt().shouldBe(1))
  // save a property
  .check(jmsProperty("foo").saveAs("fooProperty"));
jms("name").requestReply.queue("queueName")
  .textMessage("message")
  // check a String property
  .check(jmsProperty("foo").is("bar"))
  // check an int property
  .check(jmsProperty("foo").ofType[Int].is(1))
  // save a property
  .check(jmsProperty("foo").saveAs("fooProperty"))

In addition, there’s simpleCheck:

     
public boolean checkBodyTextCorrect(Message m) {
  // this assumes that the service just does an "uppercase" transform on the text
  if (m instanceof TextMessage) {
    try {
      return ((TextMessage) m).getText().equals("HELLO FROM GATLING JMS DSL");
    } catch (JMSException e) {
      throw new RuntimeException(e);
    }
  } else {
    return false;
  }
}

JmsRequestReplyActionBuilder request =
  jms("name").requestReply().queue("queueName")
    .textMessage("message")
    .check(simpleCheck(this::checkBodyTextCorrect));
fun checkBodyTextCorrect(m: Message?): Boolean {
  // this assumes that the service just does an "uppercase" transform on the text
  return if (m is TextMessage) {
      m.text == "HELLO FROM GATLING JMS DSL"
  } else {
    false
  }
}

val request = jms("name").requestReply().queue("queueName")
.textMessage("message")
.check(JmsDsl.simpleCheck { m: Message? -> checkBodyTextCorrect(m) })
def checkBodyTextCorrect(m: Message) = {
  // this assumes that the service just does an "uppercase" transform on the text
  m match {
    case tm: TextMessage => tm.getText == "HELLO FROM GATLING JMS DSL"
    case _               => false
  }
}

val request =
  jms("name").requestReply.queue("queueName")
    .textMessage("message")
    .check(simpleCheck(checkBodyTextCorrect))

Example

Short example, assuming ActiveMQ on localhost, using a reqReply query, to the queue named “jmstestq”:

     
public class TestJmsDsl extends Simulation {
  // create a ConnectionFactory for ActiveMQ
  // search the documentation of your JMS broker
  ConnectionFactory connectionFactory =
    new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616");

  // alternatively, you can create a ConnectionFactory from a JNDI lookup
  JmsJndiConnectionFactoryBuilder jndiBasedConnectionFactory = jmsJndiConnectionFactory
    .connectionFactoryName("ConnectionFactory")
    .url("tcp://localhost:61616")
    .credentials("user", "secret")
    .contextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory");

  JmsProtocolBuilder jmsProtocol = jms
    .connectionFactory(connectionFactory)
    .usePersistentDeliveryMode();

  ScenarioBuilder scn = scenario("JMS DSL test").repeat(1).on(
    exec(jms("req reply testing").requestReply()
      .queue("jmstestq")
      .textMessage("hello from gatling jms dsl")
      .property("test_header", "test_value")
      .jmsType("test_jms_type")
      .check(xpath("//foo")))
  );

  {
    setUp(scn.injectOpen(rampUsersPerSec(10).to(1000).during(60)))
      .protocols(jmsProtocol);
  }
}
class TestJmsDsl : Simulation() {
  // create a ConnectionFactory for ActiveMQ
  // search the documentation of your JMS broker
  val connectionFactory: ConnectionFactory =
    org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616")

  // alternatively, you can create a ConnectionFactory from a JNDI lookup
  val jndiBasedConnectionFactory = jmsJndiConnectionFactory
    .connectionFactoryName("ConnectionFactory")
    .url("tcp://localhost:61616")
    .credentials("user", "secret")
    .contextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory")

  val jmsProtocol = jms
    .connectionFactory(connectionFactory)
    .usePersistentDeliveryMode()

  val scn = scenario("JMS DSL test").repeat(1).on(
    exec(jms("req reply testing").requestReply()
      .queue("jmstestq")
      .textMessage("hello from gatling jms dsl")
      .property("test_header", "test_value")
      .jmsType("test_jms_type")
      .check(xpath("//foo")))
  )

  init {
    setUp(scn.injectOpen(rampUsersPerSec(10.0).to(1000.0).during(60)))
      .protocols(jmsProtocol)
  }
}
class TestJmsDsl extends Simulation {
  // create a ConnectionFactory for ActiveMQ
  // search the documentation of your JMS broker
  val connectionFactory =
    new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616")

  // alternatively, you can create a ConnectionFactory from a JNDI lookup
  val jndiBasedConnectionFactory = jmsJndiConnectionFactory
    .connectionFactoryName("ConnectionFactory")
    .url("tcp://localhost:61616")
    .credentials("user", "secret")
    .contextFactory("org.apache.activemq.jndi.ActiveMQInitialContextFactory")

  val jmsProtocol = jms
    .connectionFactory(connectionFactory)
    .usePersistentDeliveryMode

  val scn = scenario("JMS DSL test").repeat(1) {
    exec(jms("req reply testing").requestReply
      .queue("jmstestq")
      .textMessage("hello from gatling jms dsl")
      .property("test_header", "test_value")
      .jmsType("test_jms_type")
      .check(xpath("//foo")))
  }

  setUp(scn.inject(rampUsersPerSec(10).to(1000).during(60)))
    .protocols(jmsProtocol)
}

Edit this page on GitHub