JMeter and DWR
Testing a web application with JMeter is easy, but when your application uses AJAX (with DWR, for instance) and sessions, it can be a complex task.
I’ve developed an application with DWR and i want to test the performance. DWR is one of the coolest project to make an AJAX applications, IMHO.
The first aproach with JMeter is to save a set of requests to reproduce later, but those requests are asociated with a session. So, if i run concurrently those requests in several threads:
- i don’t test what i want. I want one session per thread
- maybe i obtain inconsistent data
To record a set of request, we have to:
- In Test Plan add a Config Element/HTTP Request Defaults
- In HTTP Request Defaults set a value to Server Name or IP, Port Number and Protocol
- In Test Plan add a Thread Group
- In this Thread Group add a Logic Controler/Recording Controller
- In WorkBench add a Non-Test Elements/HTTP Proxy Server
- In HTTP Proxy Server set Port, Target Controller and Pattern to Include
- In HTTP Proxy Server add a Timer/Gaussian Random Timer
- In the Gaussian Timer, set the Constant Delay Offset to ${T}
This is necesary to chage easily the host and port of all request. If you don’t use a HTTP Request Defaults, every request recorded will have a host and port value, and if you want to test another host you have to chane a lot of values.
It is a simple container for the requests.
This record the time between every request with a random deviation. It’s very important to try to reproduce the user experience.
In this screencast i introduced HTTP Cookie Manager and a listener item that didn’t be included in the above explanation. It will be used in stress time to let JMeter manage cookies to store JSESSIONID value of every thread (synthetic user) and view the results.
Now, it’s time to deploy your application and configure your browser to use the JMeter proxy.
Easy, isn’t it?
Try 1
Then, my next step was recording several users and grow up the JMeter config file. I’ve created several thread groups, one per concurrent user with distinct session IDs (remember to close the browser between every recording to clean cookies). But .., with six or seven users the files was almost 6 MB, it may vary in your project and the complexity of the user requests.
JMeter is a really cool application, but with this kind of file sizes, it needs a lot of memory. I’ve got a lot of OutOfMemoryExceptions and decided to record every new user from scratch to later merge in only one project file.
This was not a success experience, i only could get less than ten users and, the JMeter can’t use those big files, and i wasted a lot of time recording every new user, so …
Try 2
Regenerate a new session ID per thread. This seems to be easy, i have a lot of experience with xpath, and i can extract a portion of a html with it. First i created a .jsp to print the session ID:
<html>
<body>
<sessionid><%=session.getId()%></sessionid>
</body>
</html>
At the beginning of the user recording, i request this .jsp, and the i attach a Post Processor/XPath Extractor in this HTTP Request, with this values:
- Reference Name: USERSESSIONID
- XPath query: /html/body/sessionid/text()
Now i only have to replace the session IDs ocurrences in the JMeter config file (.jmx) with:
${USERSESSIONID}
I used jEdit to replace, only have to find the ID like E4B1B20074F2106ED330B98387EAF8E5 and replace all with the above text.
But … DWR needs another sessionid (script session id) and the JMeter failed
Try 3
I thought i could get DWR script session id like the session id, but minutes ago of reading the DWR code, i discover that engine.js have this values in JavaScript variables. Instead using XPath extractor y used a Regular Expresion extractor.
In the engine.js HTTP Request, attach two Regular Expresion Post Processor with:
- Reference Name: HTTPSESSIONID
- Regular Expression: DWREngine._httpSessionId = “(.*)”;
- Template: $1$
- Reference Name: SCRIPTSESSIONID
- Regular Expression: DWREngine._scriptSessionId = “(.*)”;
- Template: $1$

Then you have to replace the values like Try 2 in the DWR requests:
[...]
<stringProp name="Argument.value">1
httpSessionId=${HTTPSESSIONID}
scriptSessionId=${SCRIPTSESSIONID}
page=/smartcv2/Edit.do
c0-scriptName=MainForm
c0-methodName=setValue
c0-id=5943_1159885700394
c0-param0=string:biologicalDescriptors.dateOfBirth
c0-param1=string:October%2015%2C%201979</stringProp>
[...]
Check the .jmx file twice before loading in JMeter and if you have problems, use a TCP Monitor to see the HTTP traffic. Axis and Eclipse + WTP come with one (also netbeans, but i’ve not used yet).
See here the addendum for DWR 2.0RC2
Thanks Jorge - I’m not to familiar with JMeter, but I’ve added a link from the DWR “Around the web” page: http://getahead.ltd.uk/dwr/elsewhere .
Didn’t have time to re-create the test from your tutorial, but if it turns out to be successful, I’ll start worshiping you! Had so much trouble with testing dwr…..
I don’t understand how this will work. DWR is expecting a post with like so
callCount=1
page=/smartcv2/Edit.do
It seem to parse each line and form a map. In the case above callCount is a param key and rest of the string is value so I’m getting callCount is not a number error.
The newline post is causing lot of grief to use tools like JMeter in dwr. Why couldn’t this data is passed as normal key value pairs?
OK, my apology. Jorge’s steps actually works.
Provided you don’t edit the javaservice post request key value param from the Jmeter UI.
This will screw up the new line.
As he suggested just edit the xml file to replace the session id with the variable from regular expression extraction.
I see the following being posted now -
callCount=1
page=/demo/dwr.html
httpSessionId=B399078721DD4C38FE3AB4BD793F975B
scriptSessionId=E46E1F4BE9B1582B0DAE07A69D859D50
c0-scriptName=SearchService
c0-methodName=getResults
c0-id=0
c0-param0=boolean:false
c0-param1=string:A
batchId=0
Any editor may screw up the new line
. Having an editor with a unix style default setting (notepad on WinXp), I spent some time before figuring that out. So to be safe, switch to hex mode in your editor to make sure 0d 0a (or was it the other way around
) are in place.
/Peter Odéus
… or on second thought, jMeter seems to be bearing the responsibility; every time I choose “save” in jMeter and then switch to the reloaded file in my editor, it simply shows the current line-break style that the file currently has. So I have to manually set it to windows style in order to enforce 0d 0a line breaks.
Maybe another approach would be to, in jMeter, add a couple of \r\n (after all, it’s a java app), in the request parameter value. I’ll try it tomorrow…
Ahh, finally. In the jMeter GUI, as a child element to the test plan; add a Edit - Add - Config Element - User Defined Variables. Add a name, e.g. CRLF, and a value: ${__javaScript(’\r\n’)}
Then you alter the request parameter such that it becomes like: 1${CRLF}page=/jmeterTemplate.html${CRLF}scriptSessionId=${SCRIPTSESSIONID}${CRLF}c0-scriptName=dwrQuoteRequestService${CRLF}c0-methodName=doService${CRLF}c0-id=0${CRLF}c0-param0=string:${CRLF}c0-param1=string:${CRLF}c0-param2=boolean:false${CRLF}c0-param3=boolean:false${CRLF}c0-param4=boolean:false${CRLF}batchId=0
Good luck
:D
/Peter Odéus