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
forjava.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)
}