<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-10045102</id><updated>2012-02-02T05:37:56.846-08:00</updated><category term='Google Juice'/><category term='ethics'/><category term='Creational'/><category term='Code'/><category term='JMeter'/><category term='memory leak diagnosis'/><category term='agile'/><category term='java'/><category term='Weblogic Portal'/><category term='Performance Tuning'/><category term='weblogic'/><category term='interviews'/><category term='design'/><category term='testing'/><category term='Design Patterns'/><category term='management'/><title type='text'>Workaholic</title><subtitle type='html'>The biggest mistake we could ever make in our lives is to think we work for anybody but ourselves. 
--Brian Tracy</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>68</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-10045102.post-838073943885939821</id><published>2011-11-26T22:10:00.001-08:00</published><updated>2012-01-03T11:16:19.030-08:00</updated><title type='text'>And the winner is - Stripes!</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Recently I had the unpleasant experience of having to select a "framework" for a J2EE application.&lt;br /&gt;&lt;br /&gt;In my day job , the decisions have been usually made for me (Weblogic Portal aka BEA Weblogic Portal aka Oracle Weblogic Portal). Pageflow was ok (even though the stateful behavior made many normal HTTP operations painful). But the Portal parts were decent and we did have reusable(the holy grail!) portlets.&lt;br /&gt;&lt;br /&gt;When it was time to choose something for the web application I wanted to develop , there were quite a few options. Years ago , this would have been simple. Free , documented, widely used == Struts. Now this isn't quite so simple.&lt;br /&gt;&lt;br /&gt;The first thing I eliminated was a portal container. The standard ones use JSR-168 or 286 and in their pursuit of WSRP, Federation and other portal goodies forget that they are actually using HTTP. A web based framework that needs you to jump hoops to get the HTTPServletRequest usually indicates that the creators of the framework weren't thinking their actions through. If there ever was a J2EE spec that was worse than EJB , it's JSR 168. In their crazy pursuit of the least common denominator , we get crippled products. No thank you.&lt;br /&gt;&lt;br /&gt;I did however want something that would let me easily reuse menu's , footers , right hand modules etc. jsp:include just doesn't do it so well , where does the underlying code that fetches data for these common pages reside? If the JSP is to be just a dumb view, this is a problem.&lt;br /&gt;&lt;br /&gt;Struts shows it age (and you need Tiles to support the above and tiles is painful) . Perhaps my views are clouded due to a project that I had worked in a past life. I assume the architect(s) wanted to beef up their CV so they had Struts, Tiles, Spring, Hibernate, iBatis , ofBiz, freemarker, ofbiz's persistence framework and every single open source technology that was somewhat popular.&amp;nbsp; Getting all of these to work together was an exercise in frustration (note this was years ago) - but as soon as I am told to use Tiles I remember this project and I stop.&lt;br /&gt;&lt;br /&gt;Enter Spring. When I first used it , I was impressed with how well it did basic stuff. I loved Spring JDBC - this was better than crappy ORM frameworks(yes Hibernate , you too). It let people who knew SQL and enjoyed SQL work with SQL without the normal associated JDBC trappings (to this day , my homegrown SQL utilities closely resemble Spring JDBC API's). Spring MVC should be good , right? Perhaps it is. But the documentation sucks and I don't have that much time to invest. It also felt that Spring MVC was more concerned with Spring Integration and the MVC pattern than it was in solving the problem of a easy to use web framework (totally biased , totally unjustified view , based on a cursory reading of documentations - and apologies to the Spring team, who I salute - but really your documentation should be better if you want to draw in people like me)&lt;br /&gt;&lt;br /&gt;Enter Wicket - But then two lines from the documentation&lt;br /&gt;"JSP is by far the worst offender" "Wicket does not introduce any special syntax to HTML. Instead, it extends HTML in a standards-compliant way via a Wicket namespace that is fully compliant with the XHTML standard".&lt;br /&gt;Look at the feature list - &lt;a href="http://wicket.apache.org/meet/features.html"&gt;http://wicket.apache.org/meet/features.html&lt;/a&gt; . Does it start with simple to use , web framework , supports all web related features? No it starts with we use POJO's (i.e. you can unit test!). Wow. Because Unit testing a web application is value for money. &lt;br /&gt;Bye Bye Wicket. You've been clean bowled. I never understood the dislike JSP gang. It's like looking at bad java code saying Java is by far the worst offender. I like tag libraries when they dont attempt to be&lt;br /&gt;HTML encapsulators. I like being able to read Java code instead of the mental shift associated with interpreting yet another template framework syntax. I like the ability to embed Java code instead of new syntax , and I use it sparingly, and it works well thank you very much. I understand you might have a valid different philosophy , but it's not for me.&lt;br /&gt;&lt;br /&gt;Enter the Play framework. Seemed simple (though non JSP). All in all looked to be great and simple. Seemed to get web applications. Targets restful structures. It would be nice to learn a new framework and see what it does better and what it does worse. But the tutorials seemed to be too command line heavy. There's nothing wrong with that of course. One problem I had is since I was trying to implement this project for a friend and I would have to hand it over to someone, I needed to use something that could be easily learnt or was widely used. Play could be it - but it is so different from the rest, that I hesistate.&lt;br /&gt; &lt;br /&gt; Enter Stripes. Did I like the documentation. The HowTo seemed to cover everything I want, and the framework seemed to hit the right balance between what it did and what you had to do. Yay we have a winner. The proof of simplicity , my wife who is a PHP developer with rudimentary java knowledge picked up this framework in a couple of hours (or she is exceptionally smart and yes she reads this blog)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-838073943885939821?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/838073943885939821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=838073943885939821' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/838073943885939821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/838073943885939821'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2011/11/and-winner-is-stripes.html' title='And the winner is - Stripes!'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-3239686074083102540</id><published>2011-09-23T11:38:00.000-07:00</published><updated>2011-09-23T15:32:16.413-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Java based web frameworks</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;A quick rant on the state of web based frameworks in the J2EE world&lt;br /&gt;a. Imposing Maven on me is not nice.&lt;br /&gt;b. If your "web" based framework cannot support clean URL's you are in the wrong business when you are writing frameworks&lt;br /&gt;c. A J2EE standard doesn't mean its a good standard (JSF - Im looking at you)&lt;br /&gt;d. When you want a view technology please please use JSP. Its mature and it works. It is as good or as bad as you want it to be. Making your own template language which is either inflexible or just as bad as JSP is just plain silly. Reinventing JSTL with a different archaic syntax is silly. Doing it in the guise of "no java in JSP" is silly - There isn't a framework that I can't write bad code in.&lt;br /&gt;e. Make simple things simpler and make hard things easier if possible and it's ok if hard things remain hard. But do not make simple things simpler(oh look how quickly I can do CRUD) and hard things harder(because lets face it , every application does have corner cases).&amp;nbsp; Do not make hard thing's simpler and simple things harder (I have to set up how many files for Hello World?) - because lets face it not everything in a web application is Rocket Science.&lt;br /&gt;f. Who would have thought Spring would turn out to be more heavyweight than EJB.&lt;br /&gt;g. Who would have thought that Struts 1 would still be so heavily used&lt;br /&gt;h. Who would have thought that I would now prefer to code in ASP.net than identify which Web Framework I should use.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-3239686074083102540?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/3239686074083102540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=3239686074083102540' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3239686074083102540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3239686074083102540'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2011/09/java-based-web-frameworks.html' title='Java based web frameworks'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1081705893236054281</id><published>2011-08-11T21:33:00.000-07:00</published><updated>2011-08-13T15:42:44.885-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Random Value Selection using JMeter XPath Post Processor</title><content type='html'>JMeter has two post processor extractors which are usually used when we need some data extracted from the response. The XPath extractor is useful when the Regex would match other elements in a page (e.g. a link inside an li element). However the XPath extractor is missing a functionality that the Regex Post Processor has. It only returns all the values (equivalent to specifying -1 in a Regex Post Processor). XPath also natively supports returning the "nth" value using the position() function. However it doesn't support returning a value at random.&lt;br /&gt;However using normal JMeter functions we can easily implement this functionality.&lt;br /&gt;Assume that you have an XPath post processor that is attached to a HTTP Sampler and is returning n values into a variable called testXPATH. if we now want to select a value at random what we need to use is&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;${__V(testXPATH_${__Random(1,${testXPATH_matchNr})})}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;But thats a mouthfull and needs an explanation&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;${testXPATH_matchNr}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;returns the count of how many elements matched. We are assuming that some values are going to be selected, otherwise you need an IF controller to check the condition.&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;${__Random(1,${testXPATH_matchNr})}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Will then select an integer between 1 and the count of the values (TODO check if we need to add 1)&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;${__V(testXPATH_${__Random(1,${testXPATH_matchNr})})}}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Finally we form a string of the form testXPATH_n  e.g. testXPATH_3 which is then passed to the __V function which will get us the value for the variable&lt;br /&gt;&lt;a href="http://jakarta.apache.org/jmeter/usermanual/functions.html"&gt;http://jakarta.apache.org/jmeter/usermanual/functions.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that running TIDY on HTML , followed by parsing it to create a DOM structure and finally running an XPATH query against it is signifcantly slower than just running a Regex against a String. If you need to generate a large load and you have limited resources available to you, then the XPATH extractor is probably not the best alternative.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1081705893236054281?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1081705893236054281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1081705893236054281' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1081705893236054281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1081705893236054281'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2011/08/random-value-selection-in-xpath.html' title='Random Value Selection using JMeter XPath Post Processor'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2480517115020462287</id><published>2011-07-11T14:33:00.000-07:00</published><updated>2011-08-18T22:26:33.892-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Looping through all output of a RegExp extractor (without the for each controller)</title><content type='html'>I forget why the user couldnt use a For Each controller , but heres how to loop through the result of a Regex Post Processor that returns multiple values&lt;br /&gt;&lt;br /&gt;ThreadGroup&lt;br /&gt;+HttpSampler&lt;br /&gt;++Regex Extractor (variableName = links)&lt;br /&gt;+WhileController(${__javaScript(${C} &lt; ${links_matchNr})}) &lt;br /&gt;++HTTPSampler  use ${__V(links_${C})} to access the current result&lt;br /&gt;++Counter (start=1,increment=1,maximum=${links_matchNr},referenceName=C)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2480517115020462287?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2480517115020462287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2480517115020462287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2480517115020462287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2480517115020462287'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2011/07/looping-through-all-output-of-regexp.html' title='Looping through all output of a RegExp extractor (without the for each controller)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-3219948651402963549</id><published>2011-02-10T09:56:00.000-08:00</published><updated>2011-02-10T11:46:55.333-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Dynamic values within files</title><content type='html'>&lt;span style="font-style: italic;"&gt;I have a HTTP Post request sample to which we are passing an XML file through option "Send Files With Request". The XML file to be sent with request contain on Tag "Order id" which need to be modified [ dynamically during test plan executing] before sending the request. &lt;a href="http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/201102.mbox/%3C4E40181BDEC7704D984F42ACFA2A525803002E36@ct-beexch-4-1.cybage.com%3E"&gt;Original&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Typically in JMeter we would use a ${variableName} notation. However JMeter only replaces these values when the the ${variableName} is within the script itself , not when it is referenced in some other file. As the user wants to use a separate (template) file which is added to the HTTP request, this technique wont work.&lt;br /&gt;One option to consider is whether we could generate all the files we need before we run the test. this is possible for example when the dynamic data is a set of id's that is accessible say from a database.  In this case the better (in the more efficient sense) is to have a initialisation step (perhaps as part of the build or as a separate step in Jmeter) to create all the files that the test would need. Once this is done it is easy to make the JMeter script pick one file (usually using the &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#CSV_Data_Set_Config"&gt;CSV DataSet Config&lt;/a&gt;).&lt;br /&gt;However this isnt always possible. In the question above , the Order ID could be dynamically generated by the system under test in ways that might not be predictable. In this case we cannot generate the files in advance. We have to extend JMeter.&lt;br /&gt;The cleaner more elegant way to do this would be to write a custom pre-processor of some sort because it sounds as if this functionality could be reused in some other context (or extend the HTTPSampler).  But we will choose the quick and dirty way of writing a BeanShell preprocessor that does this for us.&lt;br /&gt;&lt;br /&gt;Briefly the solution will&lt;br /&gt;a. Have a template XML file. We will use @variableName@ within the file for what we want replaced. We will currently only support replacing a single variable (but it is easy to support multiple variables).&lt;br /&gt;b. We will configure the HTTPSampler to use a generated file. At runtime a pre - processor will read the template file and generate this new file. This new file will be read and posted by JMeter&lt;br /&gt;&lt;br /&gt;The Structure of the test is shown below&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/TVQ-YTOdQTI/AAAAAAAAQZg/WY6hH6TRnD8/s1600/FileParam.JPG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/TVQ-YTOdQTI/AAAAAAAAQZg/WY6hH6TRnD8/s320/FileParam.JPG" alt="" id="BLOGGER_PHOTO_ID_5572147226162839858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;The HTTP Sampler adds a currently non existent file to be posted. This is the file the Pre Processor will create. The name of the file is varied based on the ThreadNumber (we could have added timestamps etc as well) so that each thread will get its own file name&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/TVQ-jkUuu1I/AAAAAAAAQZo/5EM9nfZz4A0/s1600/UserDefinedVars.JPG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 53px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/TVQ-jkUuu1I/AAAAAAAAQZo/5EM9nfZz4A0/s320/UserDefinedVars.JPG" alt="" id="BLOGGER_PHOTO_ID_5572147419731114834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;We use user defined variables to define the location of the temp file, the regex that we want to run on the file and the replacement value.&lt;br /&gt;&lt;br /&gt;The BeanShell pre-processor&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;import java.io.BufferedReader;&lt;br /&gt;import org.apache.jmeter.protocol.http.util.HTTPFileArg;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.nio.MappedByteBuffer;&lt;br /&gt;import java.nio.channels.FileChannel;&lt;br /&gt;import java.nio.charset.Charset;&lt;br /&gt;import java.io.BufferedWriter;&lt;br /&gt;import java.io.FileOutputStream;&lt;br /&gt;import java.nio.channels.Channels;&lt;br /&gt;&lt;br /&gt;//read the file as string&lt;br /&gt;FileInputStream stream = new FileInputStream(new File(vars.get("templatePath")));&lt;br /&gt;String fileAsString = "";&lt;br /&gt;try {&lt;br /&gt;      FileChannel fc = stream.getChannel();&lt;br /&gt;      MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());     &lt;br /&gt;      fileAsString = Charset.defaultCharset().decode(bb).toString();&lt;br /&gt;}&lt;br /&gt;finally {&lt;br /&gt;        stream.close();&lt;br /&gt;}&lt;br /&gt;//perform the replacement&lt;br /&gt;fileAsString = fileAsString.replaceAll(vars.get("replaceRegex"), vars.get(vars.get("variableName")));&lt;br /&gt;&lt;br /&gt;//assumes first file&lt;br /&gt;HTTPFileArg arg = sampler.getHTTPFiles()[0];&lt;br /&gt;//write it out to the file we want&lt;br /&gt;FileChannel fout = new FileOutputStream(arg.getPath()).getChannel();&lt;br /&gt;BufferedWriter bf = new BufferedWriter(Channels.newWriter(fout, Charset.defaultCharset().name()));&lt;br /&gt;bf.write(fileAsString);&lt;br /&gt;bf.close();&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Disclaimer : File Reading writing snippets swiped from Google, you can probably make it more efficient.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Briefly the snippet reads the template file(location defined as a variable) as a String (using the default charset , if you deal with multiple languages you might want to force this to UTF-8).&lt;/li&gt;&lt;li&gt;It then runs the replacement using a regex (also a variable) and the subsitution value (also a variable which for this example we have just spoofed)&lt;/li&gt;&lt;li&gt;Finally it writes the file(assuming default charset , again you could force this to be UTF-8). To determine the location of the file , it reads the location from the HTTPSampler. This is currently set as the first file , but we could have used a name or any other technique.&lt;/li&gt;&lt;/ul&gt;And finally the sampler will read the file that we have created and post it as usual.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.office.live.com/self.aspx/Public/jmeter/Parameterise%20File/ParameteriseFile.jmx"&gt;Sample JMX available here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-3219948651402963549?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/3219948651402963549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=3219948651402963549' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3219948651402963549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3219948651402963549'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2011/02/dynamic-values-within-files.html' title='Dynamic values within files'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/TVQ-YTOdQTI/AAAAAAAAQZg/WY6hH6TRnD8/s72-c/FileParam.JPG' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-5088624714418417790</id><published>2011-01-26T10:38:00.001-08:00</published><updated>2011-01-26T10:42:35.440-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='memory leak diagnosis'/><title type='text'>java memory leaks</title><content type='html'>One of my colleagues asked how I diagnosed a memory leak that was impacting his application , so this is what i said. Maybe Ill write it tutorial form some time&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The version of java we are running doesnt make this easy so this is what I did on dev (its hard to make this a coherent narrative).&lt;br /&gt;&lt;br /&gt;Almost any memory leak debugging takes the following form(Im assuming the Out of Memory says the HEAP is out of memory)&lt;br /&gt;a. Run your application steps that are causing the memory leak (detecting this is actually the biggest problem but if you dont know what step is causing the leak , you basically have to access all the functionality of your application). This ensures that all statics/caches/classes are loaded. Then force a garbage collection. Then check the memory for the Java VM and take a heap dump (this is a binary form of all the objects on the heap including the allocation graph)&lt;br /&gt;b. Now repeat the step causing the problem. make sure that the  step ends correctly (for e.g. if the step is a user goes and saves the quote, ensure that you logout and invalidate his session otherwise you get false readings). Now run a full GC again. Take another heap dump.&lt;br /&gt;c. Compare the two heap dumps. if there is a difference that means you have a leak - ideally there shouldnt be a difference. In practice on a server like tomcat there are a lot of things happening in the background even if no user is accessing the site so even after a full gc , you might still see some tomcat classes or objects that appear to be new. The way around this is that you have to loop the step in b so that you will get to see significant differences for your classes rather than the app server classes.&lt;br /&gt;&lt;br /&gt;For our env however taking a  heap dump seems problematic because of the version of JDK seems really old(1.5 _07) and I wasnt able to load the taken heap dump in any tool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Heap Dump&lt;/span&gt;&lt;br /&gt;To take a heap dump you have the following options&lt;br /&gt;a. Some JVM's support -XX:+HeapDumpOnCtrlBreak (kill -3 pid on linux). However our version doesnt&lt;br /&gt;b. Some profilers(e.g. Jprobe) allow you to take heap dump - You have to pay for this but there are some free ones like NetBeans. however all of them need you to run some install steps so I didnt use this&lt;br /&gt;c. use &lt;span style="font-weight: bold;"&gt;jmap&lt;/span&gt; . This is a utility that Java provides. Later versions let you say JAVA_BIN/jmap -dump&lt;other options="" like="" format=""&gt; processid. For our version we have to say jmap -heap:format=b processid . however this isnt working correctly since i couldnt load this dump into any tool. what I finally used was jmap -histo processid. This is a poor mans heap dump . it shows the classes and the number and the size they occupy, but it doesn't show who allocated the classes (so for e.g. I knew it was the concurrency related classes that were leaking , but I didnt know who was creating them - that was thanks to Google)&lt;br /&gt;&lt;br /&gt;d. +XX:HeapDumpOnOutOfMemory - This will automatically take a heap dump when you run out of memory but debugging with this is slightly harder because you have live objects&lt;br /&gt;e. use HPROF (this is an earlier version of the tool) when you start up java but it will slow the process.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Monitoring&lt;/span&gt;&lt;br /&gt;To look at how much memory is being used, and to force GC you have the following options&lt;br /&gt;a. Look at the probe we installed (specific to tomcat)  - lambda/psi probe . Click System information . under overview you can see the memory being used and you can Force GC as well. You can also click Memory Utilization and it will show you the breakup. I had to add some JMX parameters to startup. This is tomcat specific.&lt;br /&gt;It also lets you see sessions and their footprints (sometimes the leak isnt actually a leak. Code puts too much data in session , the user doesnt log out , the session remains active for say 30 minutes , then that much memory is used up for 30 minutes. technically this isnt  aleak , when the session times out , the objects will get collected , but it looks like a leak because the memory keeps getting used , but doesnt get reclaimed)&lt;br /&gt;b. use JConsole . This is in the bin directory of your java. When you start it on your machine you can add a remote connection&lt;br /&gt;These are the settings I added on dev&lt;br /&gt;export JAVA_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/apache-tomcat-5.5.30/logs -XX:PermSize=256m -XX:MaxPermSize=256m -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dfile.encoding=UTF8"&lt;br /&gt;This will also let you see  some things that the probe does.&lt;br /&gt;Using this I could find out&lt;br /&gt;a. That it wasnt the sessions causing the problem (since the probe showed that only 1 MB was being used in sessions).&lt;br /&gt;b. I also used it to check and see whether threads were  causing issues , not the case.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Testing&lt;/span&gt;&lt;br /&gt;I used JMeter to simulate a web user going and approving a quote and simply looped that 4000 times. I couldnt not use say SOAPUI because we needed to simulate a stub being created whereas SOAP acts as the client so it wouldnt have shown the problem. Ordinarily you would not know the Stub causes the problem , but the histograph had shown such a large number of the concurrent objects on the heap , that a google search showed that other people had faced this problem with axis 1.4.1. If I didnt have this I would have had to write a script that would have placed a quote, gone and approved it , saved it , modified it etc.&lt;br /&gt;&lt;br /&gt;The histographs are in /root/histbeftest and /root/hist92per and are easily compared to verify.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Analysis&lt;/span&gt;&lt;br /&gt;The histograph files are plain text and can be compared in a text editor. If I had a heap dump we could use&lt;br /&gt;a. JHat - this comes in the bin directory of java (1.6 onwards and some update of 1.5 onwards but it can read 1.5 dumps). This will let you browse the heap and even compare them&lt;br /&gt;b. Profilers like JProbe&lt;br /&gt;c. Other tools like VisualVM, HPJmeter NetBeans, extensions in eclipse all let you load heap dumps.&lt;br /&gt;One of the issues you might run into is that the Heap Dump file is quite large and your client tool may not have enough memory. To verify a memory leak you usually reduce the amount of memory you give to the JVM so that you get smaller heap dump files (so for e.g. the iquote app once it is running and all the classes are loaded takes about 20 to 30% of 512MB which is about 150 MB. So I could reduce the memory to 256MB instead of 512 and run the tests to create a much smaller heap dump)&lt;br /&gt;&lt;br /&gt;a memory leak in sample code and then trying to detect it using tools is usually the best way to learn.&lt;/other&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-5088624714418417790?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/5088624714418417790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=5088624714418417790' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5088624714418417790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5088624714418417790'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2011/01/memory-leaks.html' title='java memory leaks'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-881229873732660792</id><published>2010-11-28T04:01:00.000-08:00</published><updated>2010-11-28T04:37:14.389-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>JMeter and AJAX - Part III</title><content type='html'>A four part post on JMeter and AJAX&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-i.html"&gt;Part I - A general discussion on why we might not need to worry about testing AJAX on JMETER&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html"&gt;Part II - A diversion on creating a sampler that will allow us to synchronize between specific threads&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-iii.html"&gt;Part III - A simple sample on executing some AJAX requests in parallel&lt;/a&gt;&lt;br /&gt;Part IV - A more complex sample&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html"&gt;Part II&lt;/a&gt; we developed a sampler that would let us synchronize selected threads. I split that out because someday I might be tempted to actually write that timer. So lets now try and execute some AJAX requests in parallel. The demo site we will use is &lt;a href="http://www.ajaxdaddy.com/demo-dhtml-autocomplete.html"&gt;http://www.ajaxdaddy.com/demo-dhtml-autocomplete.html&lt;/a&gt; (Please don't run extensive load tests against this site - it isn't mine)&lt;br /&gt;The site has an AJAX based autocomplete for countries. Access the site in FireFox, turn on Firebug and type au into the textbox and you can see the AJAX calls being made in firebug&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/TPJGDi_602I/AAAAAAAAQIw/BnfPk-t-hM0/s1600/JmeterAjaxTest2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 145px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/TPJGDi_602I/AAAAAAAAQIw/BnfPk-t-hM0/s320/JmeterAjaxTest2.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5544571117994955618" /&gt;&lt;/a&gt;&lt;br /&gt;We can see that two AJAX calls are made, one when we typed 'a' and one when we typed 'u' (There is an AJAX design pattern that applies here which doesn't seem to have been followed). So we will access this page and try to simulate two parallel calls.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/TPJHlMI0DyI/AAAAAAAAQJE/ORKBMhY0bdg/s1600/JmeterAjaxTest3.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 96px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/TPJHlMI0DyI/AAAAAAAAQJE/ORKBMhY0bdg/s320/JmeterAjaxTest3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5544572795485425442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Init and Delay Sampler are from &lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html"&gt;Part II&lt;/a&gt;. The Init sampler ensures only 1 thread does the initialization bits. The delay sampler has the rest of the code. After the Init sampler we just make all the threads wait so that no threads run before we are ready to begin (so don't use any ramp up time as that would be nullified here). Its essential the sync timer has a count equal to the count of threads in the threadgroup.&lt;br /&gt;The IF controller is used so that only the main threads perform the request to the main page. Recall for 6 threads to run 2 at a time , we have the groups as Thread(1,2) , Threads(3,4), Threads(5,6). The even numbered threads will only be used for the AJAX requests. The Odd numbered threads will be used for the main sample and the AJAX requests. In our case the landing page needs to be accessed by the odd numbered threads. The even numbered threads will skip and land at the delay sampler waiting for their respective soulmates to join them(I'm currently waiting to be reunited with my wife hence the flowery language).&lt;br /&gt;Anyway we have added a Gaussian random timer to allow the odd numbered threads to arrive at different times. When the odd numbered thread does arrive at the delay sampler, it along with its even numbered pair will be released to execute the Make AJAX request sampler (which chooses a word at random from the CSV file we have defined text,assert e.g. a,australia). &lt;br /&gt;&lt;br /&gt;Hence two requests will be executed in parallel for the AJAX request sampler. If we had further requests after this we would have added another IF controller(only odd numbered threads) and coded the  samples under this. if we wanted 3 requests in parallel we would have to adjust the Init sampler to say we want groups of 3. &lt;br /&gt;Run the test. Though the samples may appear interleaved , note down the sample start times of the groups of threads that were supposed to execute in parallel, they will be more or less the same.&lt;br /&gt;&lt;br /&gt;But I have cheated. The samples in parallel didn't really depend on each others data. The AJAX requests were exactly the same , differing in data. The AJAX requests didn't depend on the user's session thereby reducing the complexity of the script.&lt;br /&gt;&lt;br /&gt;Lets attempt an example which needs the above. Onwards to Part IV (as soon as I find a good demo!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-881229873732660792?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/881229873732660792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=881229873732660792' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/881229873732660792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/881229873732660792'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-iii.html' title='JMeter and AJAX - Part III'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/TPJGDi_602I/AAAAAAAAQIw/BnfPk-t-hM0/s72-c/JmeterAjaxTest2.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-8881362959362318726</id><published>2010-11-27T05:08:00.000-08:00</published><updated>2010-11-28T04:40:45.108-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>JMeter and AJAX - Part II</title><content type='html'>A four part post on JMeter and AJAX&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-i.html"&gt;Part I - A general discussion on why we might not need to worry about testing AJAX on JMETER&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html"&gt;Part II - A diversion on creating a sampler that will allow us to synchronize between specific threads&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-iii.html"&gt;Part III - A simple sample on executing some AJAX requests in parallel&lt;/a&gt;&lt;br /&gt;Part IV - A more complex sample&lt;br /&gt;&lt;br /&gt;As mentioned in &lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-i.html"&gt;Part I&lt;/a&gt; , the most elegant way to simulate AJAX in JMeter would be to customize the HTTPSampler to allow child HTTPSampler requests to be executed in parallel.&lt;br /&gt;Since customization of JMeter core isn't an option for me, we'll try and simulate this directly without customizing JMeter. Note that this is a toy, done for amusement rather than any real solution to an existing problem.&lt;br /&gt;&lt;br /&gt;The first thing we should note that anything that we need done in parallel in JMeter needs its own thread. Suppose we have some requests that make two AJAX requests in parallel then the way we are going to work this is&lt;br /&gt;Thread odd numbered(1,3,...) - Main thread that executes most of the requests&lt;br /&gt;Thread even numbered(2,4,...) - Thread used only when needed for AJAX parallel requests so Thread(1,2) is a group as is Thread(3,4) and so on.&lt;br /&gt;If we needed to make 3 AJAX requests in parallel then we would have grouped up Threads(1,2,3) and Threads (4,5,6) - but the main thread would have been Thread1, Thread4,...&lt;br /&gt;You can immediately see resources are being wasted - Well we did say this was a toy.&lt;br /&gt;Making the even numbered threads not execute some samplers is easy, we just need an IF controller to check. But how do you make Thread 1 and Thread 2 for e.g. execute a sampler in between at exactly the same time? In the Java world , this would usually mean reading up everything that Doug Lea and Brian Goetz have written - but in lazy developer mode this means downloading the JMeter source code and looking at SyncTimer (which blocks a fixed number of threads but not specific ones) and using the time honored technique of Copy Paste.&lt;br /&gt;So before diving into the problem at hand lets see if we can simulate the following.&lt;br /&gt;6 threads will arrive at varying times into one sampler. At which points they will wait till groups are ready i.e. Threads 1 and 2 will go together and Threads 3 and 4 will go together and so on.&lt;br /&gt;Here's the Beanshell sampler which is actually a customized Sync Timer in disguise&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;import java.util.HashMap;&lt;br /&gt;int totalThreads = 6; // MUST match total number defined in Thread Group&lt;br /&gt;int groupsOf = 2; //MUST match number of requests to make in parallel&lt;br /&gt;&lt;br /&gt;if (bsh.shared.myObj == void){&lt;br /&gt;    // not yet defined, so create it:&lt;br /&gt;    bsh.shared.myObj =new HashMap();&lt;br /&gt;    bsh.shared.timerCounter =new HashMap();&lt;br /&gt;    int numObjectsNeeded = totalThreads/groupsOf;&lt;br /&gt;    for(int i = 0;i&amp;lt;numObjectsNeeded;i++) {&lt;br /&gt;           bsh.shared.myObj.put(String.valueOf(i),new Object());&lt;br /&gt;           bsh.shared.timerCounter.put(String.valueOf(i),new int[] { 0 });&lt;br /&gt;    }&lt;br /&gt;    print(&amp;quot;populated&amp;quot;);&lt;br /&gt;} else {&lt;br /&gt;   print(&amp;quot;already init&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;print(${__threadNum()});&lt;br /&gt;&lt;br /&gt;int grpNo = (int)(${__threadNum()} -1)/groupsOf;&lt;br /&gt;print(grpNo);&lt;br /&gt;String groupNumber = String.valueOf(grpNo);&lt;br /&gt;print(groupNumber);&lt;br /&gt;Object syncObject = bsh.shared.myObj.get(groupNumber);&lt;br /&gt;print(syncObject);&lt;br /&gt;synchronized (syncObject) {&lt;br /&gt;   int[] timerCount = (int[])bsh.shared.timerCounter.get(groupNumber);&lt;br /&gt;   timerCount[0]++;&lt;br /&gt;   final int count = timerCount[0];&lt;br /&gt;   if (count &amp;gt;= groupsOf) {&lt;br /&gt;                syncObject.notifyAll();&lt;br /&gt;            } else {&lt;br /&gt;                try {&lt;br /&gt;                    syncObject.wait();&lt;br /&gt;                } catch (InterruptedException e) {&lt;br /&gt;                    log.warn(e.getLocalizedMessage());&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            timerCount[0]=0; // Reset for next time   &lt;br /&gt;}&lt;br /&gt;SampleResult.setResponseData(&amp;quot;sunk!&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The bsh.shared namespace is used to share objects between threads. So in our case we have 6 threads and we want 2 threads in parallel which means there are 3 groups of two threads each. To synchronize each group we need an object (hence 3 objects) and a counter each - to count how many threads are already available. Thats what the first part of the code sets up.(The first part is not thread safe but because we are going to test this by guaranteeing that threads arrive at different times , the snippet need not be thread safe).&lt;br /&gt;&lt;br /&gt;The second part of the code then calculates which Group a thread belongs to, gets the object for the group, increases its count. If the number of threads is less than that we want in parallel it suspends the thread (by calling wait) otherwise it does a notifyAll which will wake up all suspended threads and allow these two threads to move in parallel&lt;br /&gt;&lt;br /&gt;Heres what the test looks like&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/TPI7-QD34sI/AAAAAAAAQIo/0njyDr6Geh8/s1600/JmeterAjaxTest1.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 94px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/TPI7-QD34sI/AAAAAAAAQIo/0njyDr6Geh8/s320/JmeterAjaxTest1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5544560031895642818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We have artificially added a timer to make sure requests to the Delay sampler arrive 1 thread at a time. We run the test and we can see that Threads(1,2) run the After Delay sampler at almost the same time , as do Threads(3,4) and as do Threads(5,6)&lt;br /&gt;If we change the groupsOf in the delay sampler to be 3 then we see that three threads run in parallel.&lt;br /&gt;&lt;br /&gt;And with that we are ready to use this delay sampler to make AJAX calls in parallel.&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-iii.html"&gt;Onwards to Part III - An actual example of JMeter and AJAX&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-8881362959362318726?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/8881362959362318726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=8881362959362318726' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8881362959362318726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8881362959362318726'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html' title='JMeter and AJAX - Part II'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/TPI7-QD34sI/AAAAAAAAQIo/0njyDr6Geh8/s72-c/JmeterAjaxTest1.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1439105974485278097</id><published>2010-11-27T04:59:00.000-08:00</published><updated>2010-11-28T04:34:41.821-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>JMeter and AJAX - Part I</title><content type='html'>A four part post on JMeter and AJAX&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-i.html"&gt;Part I - A general discussion on why we might not need to worry about testing AJAX on JMETER&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html"&gt;Part II - A diversion on creating a sampler that will allow us to synchronize between specific threads&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-iii.html"&gt;Part III - A simple sample on executing some AJAX requests in parallel&lt;/a&gt;&lt;br /&gt;Part IV - A more complex sample&lt;br /&gt;&lt;br /&gt;Queries related to testing websites which use AJAX are often asked on the JMeter mailing list so here are my thoughts on this matter.&lt;br /&gt;&lt;br /&gt;JMeter is not a browser, it simulates a HTTP request/response which means it will always struggle to replicate the finer parts of browser behavior. The advantage however is that it only needs very few resources to simulate a single browser. Testing tools that actually drive a browser will find it easier to replicate the browser however they pay for it when it comes to load tests - the amount of resources is needed is much more than the JMeter family of tools. But when testing out websites which use AJAX, JMeter with its current feature set may not be an accurate simulation because AJAX does depend on the finer parts of browser behavior.&lt;br /&gt;&lt;br /&gt;An elegant solution would be to have the ability to define child HTTP requests of a parent HTTP sampler with a thread pool that defines how many of these will be made in parallel. But no such feature is currently available in JMeter.&lt;br /&gt;&lt;br /&gt;But say you do have to test an AJAX enabled site today - what can one do?&lt;br /&gt;It's useful in these times to be a lazy but honest tester - The honest part ensures that we will try to be accurate but the lazy part also ensures that we wont try to do any more than the minimum we need to do.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;So the first question that should come up is do we actually need to change anything in the way we test? The vast majority of AJAX enabled sites take the form a page loads , the user does some action , an AJAX call is made and values are shown to the user without updating the rest of the page. But look at the sequence of HTTP requests. Request for the main page, get response, browser processes response,user action, AJAX call made , AJAX response, further browser processing. There isn't any request made in parallel (ignoring all the static file requests which is its own blog post) - nor is there any difference due to Asynchronous nature of the call. So a JMeter script to simulate the above would have no difference from a normal JMeter script. the AJAX call should just follow the call to the main page and we are done.&lt;/li&gt;&lt;li&gt;But hold on some AJAX enabled sites may make an AJAX call as soon as the page loads without any user action. Or the call might be made periodically.Even in these cases the onload/onready is only done after the response of the main request is made available so while the browser may make the request asynchronously in terms of the HTTP request/response there is no difference. The periodic call may only have a problem if the time it takes to return is greater than the periodic repetition. But the latter case would be a problem anyway , all you really want from JMeter is to detect if this happens. Once it happens your system is messed up and you need to fix it! There really isn't much value simulating the messed up state. To put it in another way , if your system breaks for 50 users, there isn't much value observing how much more is broken for 100 users.&lt;/li&gt;&lt;li&gt;But hold on what if multiple AJAX requests are made on load? Say a users home page has two AJAX widgets , one which shows say his tasks , one which shows his emails? Well yes two requests will be made in parallel. Usually these requests are independent of one another. The question we really need answered is "Is there a difference between a user making two independent requests in parallel and two users(maybe with the same login) making a single independent request each in parallel?" In most cases , the answer is no. The load may be slightly higher in the latter case because you may have two sessions instead of one, but in terms of the rate of requests the server sees you can normally match the rate of requests by simply increasing the number of threads (and a little bit of math).&lt;/li&gt;&lt;li&gt;But hold on what if the requests aren't independent? What if they utilize the same table/rows causing contention when its from the same user session what if widget2 depends on widget 1 for something in the session? Well one thing to do in this case is call the developer and ask him why the hell are there two dependent requests instead of a single one? That usually doesn't end well(even though the tester is right) - but yes at this time yes you might need to actually simulate requests in parallel. Note however a lot of AJAX enabled websites dont fall into this bracket and those websites can be simulated in JMeter with a reasonable degree of accuracy.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-ii.html"&gt;Onwards to Part - 2. Simulating AJAX requests without knowing how to modify JMeter core&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1439105974485278097?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1439105974485278097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1439105974485278097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1439105974485278097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1439105974485278097'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/11/jmeter-and-ajax-part-i.html' title='JMeter and AJAX - Part I'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-7339617353730284352</id><published>2010-11-16T16:18:00.003-08:00</published><updated>2010-11-16T16:19:43.328-08:00</updated><title type='text'>Google isnt as good as you think it is</title><content type='html'>Exhibit A - A snippet from webmaster tools for this blog&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/TOMfc3uMsJI/AAAAAAAAQHs/8kkjU0ORFD8/s1600/Webmasters.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 61px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/TOMfc3uMsJI/AAAAAAAAQHs/8kkjU0ORFD8/s320/Webmasters.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5540306547450359954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Though I know that writing about deepika instead of JMeter would give me more page hits!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-7339617353730284352?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/7339617353730284352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=7339617353730284352' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/7339617353730284352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/7339617353730284352'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/11/google-isnt-as-good-as-you-think-it-is.html' title='Google isnt as good as you think it is'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/TOMfc3uMsJI/AAAAAAAAQHs/8kkjU0ORFD8/s72-c/Webmasters.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2897979750884264221</id><published>2010-10-21T17:27:00.000-07:00</published><updated>2010-10-21T17:33:20.375-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><title type='text'>WLST to dump free heap memory</title><content type='html'>&lt;pre class="source-code"&gt;&lt;code&gt;from java.io import FileWriter&lt;br /&gt;from java.io import BufferedWriter&lt;br /&gt;from java.util import Date&lt;br /&gt;connect(eval('username'),eval('password'),eval('url'))&lt;br /&gt;domainRuntime()&lt;br /&gt;cd('/ServerRuntimes/' + eval('managedServerName') + '/JVMRuntime/' + eval('managedServerName'))&lt;br /&gt;heapFreeCurrentPerOld = str(cmo.getHeapFreePercent())&lt;br /&gt;heapFreeCurrentValOld = str(cmo.getHeapFreeCurrent())&lt;br /&gt;cmo.runGC()&lt;br /&gt;java.lang.Thread.sleep(int(eval('sleepTime')))&lt;br /&gt;&lt;br /&gt;heapFreeCurrentPerNew = str(cmo.getHeapFreePercent())&lt;br /&gt;heapFreeCurrentValNew = str(cmo.getHeapFreeCurrent())&lt;br /&gt;newDate = Date()&lt;br /&gt;fstream = FileWriter(eval('outputFile'),true)&lt;br /&gt;out =  BufferedWriter(fstream)&lt;br /&gt;out.write(eval('managedServerName') + &amp;quot;,&amp;quot; + str(newDate.getTime()) + &amp;quot;,&amp;quot; + heapFreeCurrentPerOld + &amp;quot;,&amp;quot; + heapFreeCurrentValOld + &amp;quot;,&amp;quot; + heapFreeCurrentPerNew + &amp;quot;,&amp;quot; + heapFreeCurrentValNew + &amp;quot;\n&amp;quot;);&lt;br /&gt;out.close();&lt;br /&gt;disconnect()&lt;br /&gt;exit()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;There is also a property file which contains the configuration information&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;managedServerName=&amp;lt;MANAGED&amp;gt;&lt;br /&gt;username=&amp;lt;USER&amp;gt;&lt;br /&gt;password=&amp;lt;PASSWORD&amp;gt;&lt;br /&gt;url=&amp;lt;URL&amp;gt;&lt;br /&gt;sleepTime=&amp;lt;PAUSE&amp;gt;&lt;br /&gt;outputFile=&amp;lt;PathToFile.csv&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And finally to run&lt;br /&gt;&lt;br /&gt;$WL_SERVER_HOME/common/bin&gt;wlst -loadProperties &lt;PropertiesFile&gt; &lt;ScriptFile&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This was written to output the free memory before and after GC for a particular managed server (which used to run jobs) on weblogic. It was cron'ed to run at fixed intervals. The generated file is used to check if there is a memory leak. The heap free current value should remain fairly constant. if it keeps reducing , we have a leak&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2897979750884264221?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2897979750884264221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2897979750884264221' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2897979750884264221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2897979750884264221'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/10/wlst-to-dump-free-heap-memory.html' title='WLST to dump free heap memory'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2353433912261733304</id><published>2010-10-06T20:56:00.001-07:00</published><updated>2010-10-06T20:56:36.109-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Getting the current thread group name</title><content type='html'>${__BeanShell(ctx.getThreadGroup().getName())}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2353433912261733304?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2353433912261733304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2353433912261733304' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2353433912261733304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2353433912261733304'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/10/getting-current-thread-group-name.html' title='Getting the current thread group name'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1100187615787947800</id><published>2010-09-11T20:22:00.000-07:00</published><updated>2010-09-11T20:23:52.073-07:00</updated><title type='text'>Academic and Happy</title><content type='html'>via &lt;a href="http://urlai.com/url/theworkaholic.blogspot.com"&gt;http://urlai.com/url/theworkaholic.blogspot.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Text analysis&lt;/span&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com "&gt;theworkaholic.blogspot.com &lt;/a&gt;is probably written by a male somewhere between 36-50 years old. The writing style is academic and happy most of the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1100187615787947800?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1100187615787947800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1100187615787947800' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1100187615787947800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1100187615787947800'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/09/academic-and-happy.html' title='Academic and Happy'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-5454998931966018683</id><published>2010-08-03T23:44:00.000-07:00</published><updated>2010-08-20T11:32:24.674-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Jmeter with Spring Webflow</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Motivation&lt;/span&gt;&lt;br /&gt;The application uses URL containing dynamic parameters and so a record/replay fails&lt;br /&gt;&lt;a href="http://www.mail-archive.com/jmeter-user@jakarta.apache.org/msg30317.html"&gt;http://www.mail-archive.com/jmeter-user@jakarta.apache.org/msg30317.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;&lt;br /&gt;This short tutorial deals with test scripts that interact with dynamic data, and we will choose a Spring Webflow example to write a test script against.&lt;br /&gt;So we look around on Google for a sample Spring Webflow application which leads us to&lt;br /&gt;&lt;a href="http://www.springbyexample.org/simple-webflow/login.jsp"&gt;Spring By Example Sample&lt;/a&gt;&lt;br /&gt;I'm not going to use the JMeter Proxy Recorder because it seems to harm beginners more than it helps. Testers seem to get the impression that all they need to do is record and replay the script and they are done. So I shall use Firefox and LiveHttpHeaders. We are going to Login to the site and create a User&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 1: Request the Login Page&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;http://www.springbyexample.org/simple-webflow/login.jsp&lt;br /&gt;GET /simple-webflow/login.jsp HTTP/1.1&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response &lt;/span&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;Set-Cookie: JSESSIONID=[uniquevalue1]; Path=/simple-webflow&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So the first request response shows that the system sets a cookie and the name should tell us that this is a session id. [TODO]. This should also indicate to us that we need to add a cookie manager. Note the status is 200 in the Response. This is the server telling us all is well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 2: Submit Login&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;http://www.springbyexample.org/simple-webflow/loginProcess;jsessionid=[uniquevalue1]&lt;br /&gt;&lt;br /&gt;POST /simple-webflow/loginProcess;jsessionid=[uniquevalue1]&lt;br /&gt;HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue1]&lt;br /&gt;Content-Type: application/x-www-form-urlencoded&lt;br /&gt;Content-Length: 48&lt;br /&gt;j_username=david&amp;amp;j_password=newyork&amp;amp;submit=Login&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response&lt;/span&gt;&lt;br /&gt;HTTP/1.1 302 Moved Temporarily&lt;br /&gt;Date: Tue, 17 Aug 2010 05:03:48 GMT&lt;br /&gt;Set-Cookie: JSESSIONID=[uniquevalue2]; Path=/simple-webflow&lt;br /&gt;Location: http://www.springbyexample.org/simple-webflow/index.jsp&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;http://www.springbyexample.org/simple-webflow/index.jsp&lt;br /&gt;GET /simple-webflow/index.jsp HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;HTTP/1.1 302 Moved Temporarily&lt;br /&gt;Location: http://www.springbyexample.org/simple-webflow/index.html&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;http://www.springbyexample.org/simple-webflow/index.html&lt;br /&gt;GET /simple-webflow/index.html HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;a. The browser sends back the cookie that was previously set. However note that the URL also has a jsessionid which has the same value as the cookie that was set. This is known as URL rewriting. Our test will &lt;span style="font-weight: bold;"&gt;ignore &lt;/span&gt;this value because we will be using a Cookie manager&lt;br /&gt;b. The server sends a 302 response to the request. This basically asks the browser to request a new URL (the one that the Location Response Header has). Note this can happen more than once as the next request too results in a 302 response, which finally results in a 200 status code.&lt;br /&gt;&lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;HTTP Status Codes are discussed here&lt;/a&gt;&lt;br /&gt;c. The server also sends a Set-Cookie for JSessionID again with a new value. This is usually done for security reasons. We can ignore this for JMeter because the Cookie manager will handle this for us. However the sampler that we use needs to have follow redirects set. If redirect automatically is set , JMeter would not get to see this Set-Cookie header and since the application has switched the session id , if you sent it the old session id (which was associated to the before login session)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Click the Create Link&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;http://www.springbyexample.org/simple-webflow/person.html&lt;br /&gt;GET /simple-webflow/person.html HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response&lt;/span&gt;&lt;br /&gt;HTTP/1.1 302 Moved Temporarily&lt;br /&gt;Location: http://www.springbyexample.org/simple-webflow/person.html?&lt;span style="font-weight: bold;"&gt;execution=e1s1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;http://www.springbyexample.org/simple-webflow/person.html?&lt;span style="font-weight: bold;"&gt;execution=e1s1&lt;/span&gt;&lt;br /&gt;GET /simple-webflow/person.html?execution=e2s1 HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;Date: Tue, 17 Aug 2010 05:06:04 GMT&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Clicking the Create link also resulted in a 302 code so the browser issued a new request. But take a look at the URL. It has a parameter named  execution with a value e1s1. Now click the link again.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Click Create link again&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;http://www.springbyexample.org/simple-webflow/person.html&lt;br /&gt;GET /simple-webflow/person.html HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response&lt;/span&gt;&lt;br /&gt;HTTP/1.1 302 Moved Temporarily&lt;br /&gt;Location: http://www.springbyexample.org/simple-webflow/person.html?&lt;span style="font-weight: bold;"&gt;execution=e2s1&lt;/span&gt;&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;http://www.springbyexample.org/simple-webflow/person.html?&lt;span style="font-weight: bold;"&gt;execution=e2s1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GET /simple-webflow/person.html?execution=e2s1 HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The "execution" parameter value changes! So if you run the same test multiple times , the value has to be different. This is a common cause of failure of Record / Replay tests. Some of the data is dynamic. This data can be of various forms&lt;br /&gt;a. Something the application framework needs&lt;br /&gt;b. Something where the data varies (E.g. the UserId, the Product ID). Typically a user friendly string is shown on the screen but when the user performs an action , an id (usually a key in the database) is what is used by the application&lt;br /&gt;c. Dynamic fields (E.g. DHTML based applications) which get added on the fly.&lt;br /&gt;To deal with this parameter/URL we need to be able to extract the value from previous requests in our JMeter scripts.&lt;br /&gt;If you haven't developed the application it may be difficult to identify whats dynamic and whats not. The easy way is to record the script twice(With different data) and observe what changes. e.g. if you browse a product catalog , change the product.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Submit the form&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;http://www.springbyexample.org/simple-webflow/person.html?&lt;span style="font-weight: bold;"&gt;execution=e2s1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;POST /simple-webflow/person.html?&lt;span style="font-weight: bold;"&gt;execution=e2s1 &lt;/span&gt;&lt;br /&gt;HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;Content-Length: 56&lt;br /&gt;id=&amp;amp;firstName=deepak&amp;amp;lastName=shetty&amp;amp;_eventId_save=Save&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response&lt;/span&gt;&lt;br /&gt;HTTP/1.1 302 Moved Temporarily&lt;br /&gt;Location: http://www.springbyexample.org/simple-webflow/person/search.html&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;http://www.springbyexample.org/simple-webflow/person/search.html&lt;br /&gt;GET /simple-webflow/person/search.html HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Unfortunately the application has a visual bug, the added user does not show. However if you do a view source on the page and search for the username you created you can find it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Click Logout&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;http://www.springbyexample.org/simple-webflow/logout&lt;br /&gt;GET /simple-webflow/logout HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response&lt;/span&gt;&lt;br /&gt;HTTP/1.1 302 Moved Temporarily&lt;br /&gt;Set-Cookie: SPRING_SECURITY_REMEMBER_ME_COOKIE=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/simple-webflow&lt;br /&gt;Location: http://www.springbyexample.org/simple-webflow/logoutSuccess.jsp&lt;br /&gt;----------------------------------------------------------&lt;br /&gt;http://www.springbyexample.org/simple-webflow/logoutSuccess.jsp&lt;br /&gt;GET /simple-webflow/logoutSuccess.jsp HTTP/1.1&lt;br /&gt;Cookie: JSESSIONID=[uniquevalue2]&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;Set-Cookie: JSESSIONID=[uniquevalue3]; Path=/simple-webflow&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The JMeter Script&lt;/span&gt;&lt;br /&gt;Now that we know the above we can get to writing the script&lt;br /&gt;&lt;br /&gt;Most of the script is pretty much standard(All Samplers use follow redirects and we have added a Cookie Manager), till we get to the point where we need to extract out the URL.&lt;br /&gt;The Request Create Sampler extracts out the URL. Since we know that the application is going to redirect us , the extracter will extract out the last URL we will be on&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/TG7IXmIojzI/AAAAAAAAQFE/ys93Erj95Yo/s1600/ExtractURL.JPG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 118px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/TG7IXmIojzI/AAAAAAAAQFE/ys93Erj95Yo/s320/ExtractURL.JPG" alt="" id="BLOGGER_PHOTO_ID_5507559702020001586" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Post Create Data Sampler simply uses this extracted URL&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/TG7IjtD90uI/AAAAAAAAQFM/RPeUSJj3O3I/s1600/PostURL.JPG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 107px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/TG7IjtD90uI/AAAAAAAAQFM/RPeUSJj3O3I/s320/PostURL.JPG" alt="" id="BLOGGER_PHOTO_ID_5507559910037902050" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note that all samplers have assertions that verify the behavior, so if something goes wrong the Assertion should fail. For e.g. after creating the user we verify that the user we created exists on the page. When requesting a page the assertions verify some text on the page that is unique to the page.&lt;br /&gt;Run the test, we get no errors! Modify the ThreadGroup to have two threads and two iterations. Run the test , everything should pass. Now look at the View Results Tree listener. You should see the redirects being followed (multiple children results under a parent). But do you see different values for the execution parameter? No - This is because each thread is its own session and each user will start with the same parameter value. Even having multiple iterations on the thread group doesnt give you different values because we are logging out at the end of the script so the next iteration is a new session.&lt;br /&gt;&lt;br /&gt;Try adding a Loop controller to create 10 users. Note that the loop controller must enclose the Request Create and Post Create samplers (because we need to extract a new value for the execution parameter every time!). Using View results tree you can now observe the execution parameter changing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Sample Script&lt;/span&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.office.live.com/self.aspx/Public/jmeter/Spring%20Webflow/SpringWebflow.jmx"&gt;Spring Webflow.jmx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.office.live.com/self.aspx/Public/jmeter/Spring%20Webflow/SpringWebflowWithLoop.jmx"&gt;Spring Webflow with loop.jmx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-5454998931966018683?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/5454998931966018683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=5454998931966018683' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5454998931966018683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5454998931966018683'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/08/jmeter-with-spring-webflow.html' title='Jmeter with Spring Webflow'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_AOk-4gocLaw/TG7IXmIojzI/AAAAAAAAQFE/ys93Erj95Yo/s72-c/ExtractURL.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2460395651473207488</id><published>2010-06-17T21:52:00.000-07:00</published><updated>2010-06-17T21:56:28.875-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Weblogic Portal'/><title type='text'>First weblogic portal expert</title><content type='html'>YAY!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/TBr70Xnm5SI/AAAAAAAAP6E/yiIPcAEty8o/s1600/OTN+Discussion+Forums+-+WebLogic+Portal_1276836743959.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 293px; height: 320px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/TBr70Xnm5SI/AAAAAAAAP6E/yiIPcAEty8o/s320/OTN+Discussion+Forums+-+WebLogic+Portal_1276836743959.png" alt="" id="BLOGGER_PHOTO_ID_5483972373388911906" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Thankfully a lot of posters don't use Google, otherwise I couldn't answer the same questions again!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2460395651473207488?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2460395651473207488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2460395651473207488' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2460395651473207488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2460395651473207488'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/06/first-weblogic-portal-expert.html' title='First weblogic portal expert'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_AOk-4gocLaw/TBr70Xnm5SI/AAAAAAAAP6E/yiIPcAEty8o/s72-c/OTN+Discussion+Forums+-+WebLogic+Portal_1276836743959.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-7143224477409858750</id><published>2010-05-27T14:07:00.000-07:00</published><updated>2010-05-27T14:08:26.938-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='interviews'/><title type='text'>Updated JEE Interview Questions - Draft</title><content type='html'>JSP&lt;br /&gt;What are the various way's to handle  exceptions in a web application. What would you use when. Demonstrate  with  examples from any project you have worked on&lt;br /&gt;What are the  various way's  you have implemented security in your web application. Also mention  alternatives  that can be used&lt;br /&gt;Which framework have you  used. Please describe the shortcomings in the framework and the ways to  work  around them&lt;br /&gt;What is the difference between a static include,  jsp:include,  jsp:forward and redirect. Please give one example of each.&lt;br /&gt;Describe  some  Tag Libraries you have written. What are advantages / disadvantages of  tag  library. If possible give an example of a badly written open source JSP  tag  library(or any of your own) and how you would improve it.&lt;br /&gt;Give one  example  of when you would use a filter. How do you execute a filter after the  request?&lt;br /&gt;Give one example of when you would use a listener. Which  listeners have you used in your project?&lt;br /&gt;Besides defining servlets ,  name  one feature that can be specified in the web deployment descriptor&lt;br /&gt;Name   JSP implicit object. Give one example of the use of each implicit  object. Is  exception an implicit object? If so can i write  exception.printStackTrace in any  JSP? what will it print?&lt;br /&gt;Comment whether a JSP web application works  with  cookies disabled.&lt;br /&gt;Which web container did you use. Please describe  how to  use a container specific feature.&lt;br /&gt;Describe some JSTL tags you have  used  and what they are useful for&lt;br /&gt;How do you use a datasource in a JSP?&lt;br /&gt;How  do you internationalize a web application. What all do you need to take  care  of&lt;br /&gt;&lt;br /&gt;EJB&lt;br /&gt;How do you implement security in an EJB . Why does the  framework provided security not work in most real world scenarios? (or  does it?)&lt;br /&gt;If an MDB throws an Exception what happens to the message?&lt;br /&gt;If  an EJB has two methods M1 and M2 both with RequiresNew and M1 makes a  call to M2 by calling it (because M2 is a method in the same class) how  many transactions are there?&lt;br /&gt;What limitations are&lt;br /&gt;&lt;br /&gt;JDBC&lt;br /&gt;Lets say you want to execute a  query and show some data. Walk through the steps to do this in Raw JDBC.&lt;br /&gt;What  do you prefer using  of the following and why?  CMP/JDO/ORMs (like  hibernate/toplink)/SQL helpers (like Spring/iBatis)/Raw SQL?&lt;br /&gt;In the context of ORM what is lazy loading/eager load. What do you use  in your project? Why? What factors determine what is to be used.&lt;br /&gt;Your  ORM based system is slow. How would you diagnose the problem?&lt;br /&gt;Why is  pessimistic locking not useful in a web-application (or is it?)&lt;br /&gt;&lt;br /&gt;JMS&lt;br /&gt;Say you have a queue. The Producer can produce messages much  faster than the consumer can consume. What are your options?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;JMX&lt;br /&gt;Give  any example where you have used JMX&lt;br /&gt;&lt;br /&gt;WEB&lt;br /&gt;Given a large data  set , what options do you have for displaying this dataset. Which one do  you prefer and why?&lt;br /&gt;Suppose you are tasked to implement an AJAX based system where the user  types in a word in a search box and you want to show him possible  queries (e.,g. in Google if you type dee you get deepak chopra or  deepika padukone)in a drop down , what considerations would you have in   implementing the AJAX parts of the client (Assume that you have a  server side component that can give you the results)&lt;br /&gt;If you want Google to search your site easily , what do you need to take  care of in your web app&lt;br /&gt;&lt;br /&gt;Misc&lt;br /&gt;You have a clustered J2EE web  application. You need to batch process a file which has a billion  records. Each record is independent . How do you do it?&lt;br /&gt;You have a table which has UserID (primary key) and UserName. The  requirement is to display this in a drop down box on a page so that the  user will select the name but the value posted to the next page will be  the userid. The data displayed must be sorted by username. The DB  developer asks you what data structure he needs to return the results  in. What is your answer? Assuming that you get this data structure , is  there any comment you wish to make on your implementation?&lt;br /&gt;Name a few design patterns that you see being used in the Java API with  examples.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-7143224477409858750?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/7143224477409858750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=7143224477409858750' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/7143224477409858750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/7143224477409858750'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/05/updated-jee-interview-questions-draft.html' title='Updated JEE Interview Questions - Draft'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-8439045845491662868</id><published>2010-04-07T11:15:00.001-07:00</published><updated>2010-04-07T11:15:51.991-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Weblogic Portal'/><title type='text'>Simplified procedure for Syncing Embedded LDAP with Weblogic Portal Database</title><content type='html'>a. Shut down servers&lt;br /&gt;b. On the admin server, backup the LDAP directory \servers\AdminServer\data\ to another location&lt;br /&gt;c. Delete the internal LDAP directory at \servers\AdminServer\data\ldap (also from managed&lt;br /&gt;servers if applicable)&lt;br /&gt;d. Delete data from the p13n entitlement tables (delete from tablename)&lt;br /&gt; ( namely p13n_entitlement_role, p13n_entitlement_resource,p13n_entitlement_policy, p13n_entitlement_application and p13n_delegated_hierarchy )&lt;br /&gt;e. Start the servers&lt;br /&gt;f.  Redeploy the application&lt;br /&gt;g. Recreate the SAML relying party configuration&lt;br /&gt;h. Recreate Entitlements&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-8439045845491662868?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/8439045845491662868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=8439045845491662868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8439045845491662868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8439045845491662868'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/04/simplified-procedure-for-syncing.html' title='Simplified procedure for Syncing Embedded LDAP with Weblogic Portal Database'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2810071795062348356</id><published>2010-03-19T18:32:00.000-07:00</published><updated>2010-03-19T19:17:31.619-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Dynamic Parameters in JMeter</title><content type='html'>&lt;b&gt;Motivation&lt;/b&gt; &lt;div&gt;You need to send a variable number of parameters with an HTTP request i.e. the number of parameters are not known when the script is written. For example a User can register with a number of accounts , but this number varies per user. Or perhaps you want to Post process extract a number of hidden fields on the previous response and post all of them in the next Request, but you either don't know the number or there are too many fields to enter manually into the HTTPSampler.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;Use a BeanShell PreProcessor to dynamically add variables to the sampler. The relevant code is &lt;a href="http://jakarta.apache.org/jmeter/api/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.html#addArgument(java.lang.String, java.lang.String)"&gt;sampler.addArgument(name,value)&lt;/a&gt;[1]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;b&gt;Sample&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;We will write a script to access a page , extract out data based on a pattern and send these as separate parameters to the next request. The script is as shown below.&lt;/div&gt;&lt;div&gt;We make a request to some dummy page and then we have a regex extractor to extract out multiple values. In this case the Regex extracts out all words(Match No = -1) beginning with test&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/S6QuLAM8-vI/AAAAAAAAPec/P-SwWJQ5XSY/s1600-h/Regex.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 145px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/S6QuLAM8-vI/AAAAAAAAPec/P-SwWJQ5XSY/s320/Regex.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5450532215592909554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then we have a Debug Sampler to verify the regex is working, notice the results in View Results Tree Listener. The Regex has a reference variable name of &lt;b&gt;inputTerms. &lt;/b&gt;The response of the Debug sampler is shown below&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/S6QuQKTDkmI/AAAAAAAAPek/sT4hAGQp7Fs/s1600-h/regexResponse.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 291px; height: 320px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/S6QuQKTDkmI/AAAAAAAAPek/sT4hAGQp7Fs/s320/regexResponse.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5450532304202207842" /&gt;&lt;/a&gt;&lt;br /&gt;You can see from the Listeners response tab that the total number of results is 14 , available under the key inputTerms_matchNr and that each result is available as inputTerms_$resultnumber. &lt;/div&gt;&lt;div&gt;The matching groups which we usually do not need are available as inputTerms_$resultnumber_g$groupnumber. Armed with this information, the beanshell preprocessor script is trivial as shown below&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;int count = Integer.parseInt(vars.get("inputTerms_matchNr"));&lt;br /&gt;for(int i=1;i&amp;lt;=count;i++) { //regex counts are 1 based&lt;br /&gt;sampler.addArgument("hardcodedkey", vars.get("inputTerms_" + i));&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Heres the next request to which the beanshell pre processor is attached. We have one predefined variable and the rest will be dynamically added by beanshell.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/S6QuUPqlT_I/AAAAAAAAPes/IjIP4aCiCEY/s1600-h/Request.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 174px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/S6QuUPqlT_I/AAAAAAAAPes/IjIP4aCiCEY/s320/Request.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5450532374362542066" /&gt;&lt;/a&gt;&lt;br /&gt;Next we check the request data we are posting using the Request tab of the View Results Tree Listener&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/S6QvoEkU-eI/AAAAAAAAPe0/ONPXBB7DJWE/s1600-h/viewresults.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 117px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/S6QvoEkU-eI/AAAAAAAAPe0/ONPXBB7DJWE/s320/viewresults.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5450533814492527074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Notice that the argument we added to the next request was sent, as were all the parameters we added dynamically. The parameter values were also encoded.&lt;/div&gt;&lt;div&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;br /&gt;[1] &lt;a href="http://jakarta.apache.org/jmeter/api/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.html"&gt;Javadocs for HTTP Sample Base&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2810071795062348356?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2810071795062348356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2810071795062348356' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2810071795062348356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2810071795062348356'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/03/dynamic-parameters-in-jmeter.html' title='Dynamic Parameters in JMeter'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_AOk-4gocLaw/S6QuLAM8-vI/AAAAAAAAPec/P-SwWJQ5XSY/s72-c/Regex.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4704248029180326129</id><published>2010-03-15T16:14:00.000-07:00</published><updated>2010-03-15T16:20:16.304-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Asserting MS Office formats</title><content type='html'>As a follow up to the &lt;a href="http://theworkaholic.blogspot.com/2010/03/asserting-pdfs.html"&gt;PDF post&lt;/a&gt;, you can do something similar using &lt;a href="http://poi.apache.org/"&gt;Apache POI&lt;/a&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;import org.apache.poi.POITextExtractor;&lt;br /&gt;import org.apache.poi.extractor.ExtractorFactory;&lt;br /&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;&lt;br /&gt;ByteArrayInputStream bais = new ByteArrayInputStream(in);&lt;br /&gt;POITextExtractor extractor = ExtractorFactory.createExtractor(bais);&lt;br /&gt;prev.setResponseData(extractor.getText());&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;You should be able to parse word documents and excel and ppt's using this beanshell post processor. Remember to copy the POI libraries to JMeter/lib&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Future work&lt;/span&gt;&lt;br /&gt;Look into &lt;a href="http://lucene.apache.org/tika/"&gt;Apache Tika&lt;/a&gt; for a unified interface (may need to sacrifice some functionality like the startPage endPage of &lt;a href="http://pdfbox.apache.org/"&gt;PDFBox&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4704248029180326129?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4704248029180326129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4704248029180326129' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4704248029180326129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4704248029180326129'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/03/asserting-ms-office-formats.html' title='Asserting MS Office formats'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-9049348968112100301</id><published>2010-03-15T13:15:00.000-07:00</published><updated>2010-03-15T16:19:18.372-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><title type='text'>Asserting PDF's</title><content type='html'>A &lt;a href="http://www.mail-archive.com/jmeter-user@jakarta.apache.org/msg28837.html"&gt;question&lt;/a&gt; on the JMeter mailing list regarding extracting/asserting text inside a PDF file and since I ran into this for a functional scenario , I wrote up my attempt.&lt;br /&gt;I use &lt;a href="http://pdfbox.apache.org/"&gt;PDFBox &lt;/a&gt;as the library. Download the binaries and copy pdfbox-1.0.0.jar and external/fontbox-1.0.0.jar into JMeter's lib directory.&lt;br /&gt;We'll access the PDF at &lt;a href="http://jakarta.apache.org/jmeter/usermanual/jmeter_distributed_testing_step_by_step.pdf"&gt;http://jakarta.apache.org/jmeter/usermanual/jmeter_distributed_testing_step_by_step.pdf&lt;/a&gt; and check that the PDF does contain "Distributed Testing Step-by-step"&lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/PDF/PDF.jmx"&gt;JMeter sample script&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/S56XKzgdtQI/AAAAAAAAPdY/lNZi7mMXrt8/s1600-h/PDF.JPG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 293px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/S56XKzgdtQI/AAAAAAAAPdY/lNZi7mMXrt8/s320/PDF.JPG" alt="" id="BLOGGER_PHOTO_ID_5448958811045737730" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So we have a transaction controller 'Check PDF' so that we only get a result item. The HTTP Request Sampler 'Request PDF' requests the PDF. The bulk of the code is in the beanshell post processor titled 'Extract Text'&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.StringWriter;&lt;br /&gt;import org.apache.pdfbox.pdmodel.PDDocument;&lt;br /&gt;import org.apache.pdfbox.util.PDFTextStripper;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PDDocument document = null;&lt;br /&gt;StringWriter sw = new StringWriter();&lt;br /&gt;try {&lt;br /&gt;ByteArrayInputStream bais = new ByteArrayInputStream(data);&lt;br /&gt;document = PDDocument.load(bais);&lt;br /&gt;PDFTextStripper stripper = new PDFTextStripper("UTF-8");&lt;br /&gt;stripper.setSortByPosition( false );&lt;br /&gt;stripper.setShouldSeparateByBeads( true );&lt;br /&gt;stripper.setStartPage( 1 );&lt;br /&gt;stripper.setEndPage(Integer.MAX_VALUE );&lt;br /&gt;stripper.writeText( document, sw );&lt;br /&gt;} catch (Throwable t) {&lt;br /&gt;t.printStackTrace();&lt;br /&gt;sw.append("ERROR");&lt;br /&gt;} finally {&lt;br /&gt;sw.close();&lt;br /&gt;document.close();&lt;br /&gt;}&lt;br /&gt;vars.put("extractedText", sw.toString());&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;All this does is use the PDFBox API to extract text from the PDF (bytes are present in the data object) and write it to a variable in JMeter , extractedText.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The next sampler is a Java Sampler which sets the ResultData to ${extracted text}. This will echo back the contents of this variable as the response of the sampler.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/S56YLBW-SFI/AAAAAAAAPdg/ds8LJJORXzE/s1600-h/pdfjava.JPG"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 124px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/S56YLBW-SFI/AAAAAAAAPdg/ds8LJJORXzE/s320/pdfjava.JPG" alt="" id="BLOGGER_PHOTO_ID_5448959914275653714" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once this is done , you can use a normal response assertion,  regex extractor or whatever else you need to process the text&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt;: as mentioned by Milamber  in the comments , you can instead have the last line of the beanshell  as&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;prev.setResponseData(sw.toString());&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; This  will set the response of the HTTPSampler to be the text value and allow you to directly specify the assertion (and you can also   eliminate the transaction controller).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt; : if you are interested in MS office formats then follow the steps in this post, just change the BeanShell post processor to that mentioned in &lt;a href="http://theworkaholic.blogspot.com/2010/03/asserting-ms-office-formats.html"&gt;Asserting MS Office Formats&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Future work&lt;/span&gt;&lt;br /&gt;a. make a custom PDF(or any format sampler) with the options that are hardcoded (e.g. startPage or endPage)&lt;br /&gt;b. experiment with ways to use less memory. Typically should extract and write to file and use that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-9049348968112100301?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/9049348968112100301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=9049348968112100301' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/9049348968112100301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/9049348968112100301'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/03/asserting-pdfs.html' title='Asserting PDF&apos;s'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/S56XKzgdtQI/AAAAAAAAPdY/lNZi7mMXrt8/s72-c/PDF.JPG' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-9220628997271977615</id><published>2010-02-07T19:43:00.000-08:00</published><updated>2010-04-01T12:34:34.008-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Random stuff on jmeter testing</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt;  : I realized that much of what I wanted to say has already been said and in a far better manner in &lt;a href="http://msdn.microsoft.com/en-us/library/bb924357.aspx"&gt;Perfomance testing patterns and practices&lt;/a&gt;.&lt;br /&gt;One of the questions asked on the JMeter mailing list was &lt;blockquote&gt;How do I analyse my application with JMeter?&lt;/blockquote&gt;There are various reasons one might run a load test broadly detection, simulation, verification and analysis. The type of test or the scripts you might write, what you would measure or track would vary a bit depending on what you want to do. JMeter is good for simulation and verification. It is an aid to detection and analysis but you usually need other tools to help you out.&lt;br /&gt;&lt;br /&gt;Detection&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You want to find out if your application behaves correctly when accessed by multiple threads. Whether your database starts showing deadlocks or whether you might have race conditions.&lt;/li&gt;&lt;li&gt;You want to find out if your application has memory leaks.&lt;/li&gt;&lt;/ul&gt;Simulation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You want to find out how your application behaves under standard load or how it behaves under some peak load(e.g. shopping during the holidays). Response times etc.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;In the specific case of Java based web applications you want to know how often your GC cycles might run or how long.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;You application makes remote calls(e.g. webservice calls) and you want to know whether all the resources are recovered correctly. perhaps you have some throttling mechanisms in place and you want to see that its working correctly&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Verification&lt;br /&gt;&lt;ul&gt;&lt;li&gt; You want to verify the result of changing some tuning parameters.&lt;/li&gt;&lt;li&gt;You want to check your SLA's are met&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Analysis&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You might already know there is a problem and you want to simulate load while you are profiling the application.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;These areas overlap and I've used the above categories quite broadly to merely illustrate that your objective and hence your test script will vary based on your objective.&lt;br /&gt;&lt;br /&gt;For e.g.&lt;br /&gt;You want to find out if your application behaves correctly when accessed by multiple threads - In this case your test script would only be concerned with running some parts of the applications at exactly the same time. You'd want to exercise multiple parts of your application. Perhaps you are aware that some part of the application internally spawns threads and you'd run a test that exercise that area for a long time or with a high load. You don't at this point really care whether these are unrealistic scenarios or non representative scenarios, nor are you really looking at what the response times are. All you care about is do you see stuck threads or deadlocks. Do you see a really long wait time for most threads though some threads finish really fast.&lt;br /&gt;&lt;br /&gt;Or perhaps you want to tune a memory parameter and you want to verify the change&lt;br /&gt;In this case Response Times / Throughput really matter (for the same test of course). You'd first take a baseline reading without the tuning, and then another with the tuning. The test scripts must be representative of actual user behavior.&lt;br /&gt;&lt;br /&gt;Perhaps you want to check whether your site can handle holiday shopping onslaughts. In this case you would modify your tests to show bursts of activity, you'd closely monitor response times but you also want to check what happens on the server. How much memory, How much CPU. You might also want to see what load might actually bring down your servers. You might want to check if your load balancers evenly distribute the load.&lt;br /&gt;&lt;br /&gt;Or perhaps you have certain Service Level Agreements and you need to know response times accurately for the load specified in your agreement. In this case you need a representative user journey and you also need representative background users.&lt;br /&gt;&lt;br /&gt;All of which means there is no easy answer to ' How do I analyse my application with JMeter'. It can only be answered by What is it that you want to analyse (normally answered as  well, performance).&lt;br /&gt;&lt;div id="RenderTime"&gt;&lt;/div&gt;&lt;br /&gt;Lets take the most common use case, what is the 'response time' for my application.&lt;br /&gt;However actually getting the response time is more difficult than reading the response time calculation from the JMeter test results.&lt;br /&gt;This is problematic due to&lt;br /&gt;a. JMeter is not a browser and does not render the page. Different browsers take different times to render the same page. Compare older versions of Internet explorer with Chrome for e.g.&lt;br /&gt;b. A returning user with some files cached will probably show lesser times than a first time user.&lt;br /&gt;c. The network / connection speed from which the user is accessing the application may be significant. And your users may be spread out throughout the world.&lt;br /&gt;d AJAX based applications / DHTML applications are difficult to predict because not only does it vary by browser , but the number of calls that a browser may make in parallel is also different, but some calls will be made in parallel and its difficult to know that.&lt;br /&gt;&lt;br /&gt;So any response time would have (roughly speaking)&lt;br /&gt;a. The time it takes for the application to actually respond with all the data&lt;br /&gt;b. The time it takes for this data to be transferred over the network&lt;br /&gt;c. The time it takes to download static files (bearing in mind that not all files may be downloaded and that browsers may request multiple static files in parallel)&lt;br /&gt;d. The time it actually takes to render the page.&lt;br /&gt;&lt;br /&gt;JMeter can help you out with a, b, and c. but what it is good at, is finding out a. for the network on which it is running on.&lt;br /&gt;&lt;br /&gt;Typically your requirements might define an Service Level agreement for your site as Browsing operations must take &lt; 6seconds 90% of the time and shopping operations must take &lt;8 seconds 90% of the time. You also know how much large your pages are  and you can guesstimate  how much time it would take for the page to be transferred over the internet. You might take an average with some safety factor or you might take a worst case scenario. Using a browser tool like YSlow or Googles PageSpeed , you can also have some insight on how your static are downloaded , how long they take etc. And you might add some time for how long the browser takes to render. After considering all of this you might arrive at a new figure that on a high bandwidth intranet (which thereby eliminates most of the network variables) your browsing operations must take &lt; 2 seconds just to get the data and your shopping operations must take &lt; 4 seconds for your SLA's to hold because the rest of the time has already been used by the other factors.&lt;br /&gt;After this you would have to write a script which generates representative loads (for the operations being verified and the operations that would happen in the background), run the test and verify the 90% percentile lies below the value you have calculated above. But perhaps it doesn't. Static files can be optimised by reducing their number, their size, gzipping them adding expiry headers etc, but maybe you have already done this. The Clients network and browser aren't within your control so there isn't much you can do there. The next step is figuring out where your problem lies. JMeter can't help you there, you need a different set of tools. But JMeter can help you to simulate load or parts of it so that you can monitor your application with the tools of your choice. Some of your findings may be infrastructure related, Some may be code you'd have to make changes and retest and repeat.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-9220628997271977615?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/9220628997271977615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=9220628997271977615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/9220628997271977615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/9220628997271977615'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/02/random-stuff-on-jmeter-testing.html' title='Random stuff on jmeter testing'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2466989462343489619</id><published>2010-01-23T13:23:00.000-08:00</published><updated>2010-01-23T13:24:20.598-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='interviews'/><title type='text'>JSP Interview questions</title><content type='html'>1. What are the various way's to handle exceptions in a web application. What would you use when. Demonstrate with examples from any project you have worked on&lt;br /&gt;2. What are the various way's you have implemented security in your web application. Also mention alternatives that can be used&lt;br /&gt;3. When would you use servlets. name one thing you can do with a servlet that you cannot do with a JSP.&lt;br /&gt;4. Which framework have you used. Please describe the shortcomings in the framework and the ways to work around them&lt;br /&gt;5. What is the difference between a static include, jsp:include, jsp:forward and redirect. Please give one example of each.&lt;br /&gt;6  Describe some Tag Libraries you have written. What are advantages / disadvantages of tag library. If possible give an example of a badly written open source JSP tag library(or any of your own) and how you would improve it.&lt;br /&gt;7. Give one example of when you would use a filter. How do you execute a filter after the request?&lt;br /&gt;8. Give one example of when you would use a listener.  Which listeners have you used in your project?&lt;br /&gt;9.  Besides defining servlets ,  name one feature that can be specified in the web deployment descriptor&lt;br /&gt;10.  Name JSP implicit object. Give one example of the use of each implicit object. Is exception an implicit object? If so can i write exception.printStackTrace in any JSP? what will it print?&lt;br /&gt;11. Comment whether a JSP web application works with cookies disabled.&lt;br /&gt;12. Which web container did you use. Please describe how to use a container specific feature.&lt;br /&gt;13.  Describe some JSTL tags you have used and what they are useful for&lt;br /&gt;14. How do you use a datasource in a JSP?&lt;br /&gt;15. How do you internationalize a web application. What all do you need to take care of&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2466989462343489619?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2466989462343489619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2466989462343489619' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2466989462343489619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2466989462343489619'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/01/jsp-interview-questions.html' title='JSP Interview questions'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4625568230359482112</id><published>2010-01-11T12:17:00.000-08:00</published><updated>2010-01-13T10:58:07.606-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>JMeter Graphs and ANT</title><content type='html'>A follow up to the previous posts, I've integrated the graph code with ANT so that the HTML reports provided by running JMeter from the command line and styling them can be extended to include the graphs.&lt;br /&gt;&lt;br /&gt;The sample report that I generated is shown below&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/S0uJJeumW9I/AAAAAAAAOso/rx57KmBM3Uw/s1600-h/Load+Test+Results_1263241360515.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 145px; height: 320px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/S0uJJeumW9I/AAAAAAAAOso/rx57KmBM3Uw/s320/Load+Test+Results_1263241360515.png" alt="" id="BLOGGER_PHOTO_ID_5425580972058237906" border="0" /&gt;&lt;/a&gt;The custom report hyperlinks the titles of the normal summary tables to lead to graphs for the same.&lt;br /&gt;To implement this we need to&lt;br /&gt;a. Allow the graph code to be invoked from ANT. This can be done by writing a simple java class with a main method that passes parameters on the command line, or we could write a custom ant task. I wrote a custom ant task as a proof of concept.  We need to customise the build script as well&lt;br /&gt;b.Modify the XSLT to write out image anchors.&lt;br /&gt;&lt;br /&gt;These steps are described below.&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;The custom ant Task&lt;/span&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;public class AggregateGraphTask extends Task {&lt;br /&gt;private String outputDir;&lt;br /&gt;private String outputFilePrefix;&lt;br /&gt;private Boolean showThreshold = Boolean.TRUE;&lt;br /&gt;private Double threshold = 500D;&lt;br /&gt;private String jmeterResultFile;&lt;br /&gt;private String jmeterHome;&lt;br /&gt;&lt;br /&gt;public String getJmeterHome() {&lt;br /&gt;    return jmeterHome;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setJmeterHome(String jmeterHome) {&lt;br /&gt;    this.jmeterHome = jmeterHome;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public String getJmeterResultFile() {&lt;br /&gt;    return jmeterResultFile;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setJmeterResultFile(String jmeterResultFile) {&lt;br /&gt;    this.jmeterResultFile = jmeterResultFile;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public String getOutputDir() {&lt;br /&gt;    return outputDir;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setOutputDir(String outputDir) {&lt;br /&gt;    this.outputDir = outputDir;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public String getOutputFilePrefix() {&lt;br /&gt;    return outputFilePrefix;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setOutputFilePrefix(String outputFilePrefix) {&lt;br /&gt;    this.outputFilePrefix = outputFilePrefix;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Boolean getShowThreshold() {&lt;br /&gt;    return showThreshold;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setShowThreshold(Boolean showThreshold) {&lt;br /&gt;    this.showThreshold = showThreshold;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Double getThreshold() {&lt;br /&gt;    return threshold;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setThreshold(Double threshold) {&lt;br /&gt;    this.threshold = threshold;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public void execute() throws BuildException {&lt;br /&gt;    try {&lt;br /&gt;        GraphClient.init(jmeterHome);&lt;br /&gt;        String outputPrefix = outputDir +  File.separator + outputFilePrefix;&lt;br /&gt;        if(Boolean.TRUE.equals(showThreshold))  {&lt;br /&gt;            GraphClient.writeAggregateChartWithThreshold(jmeterResultFile, outputPrefix, showThreshold, threshold);&lt;br /&gt;        } else {&lt;br /&gt;            GraphClient.writeAggregateChart(jmeterResultFile, outputPrefix)    ;&lt;br /&gt;        }&lt;br /&gt;    } catch(Exception e) {&lt;br /&gt;        throw new BuildException(e);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a pretty straightforward class which calls our API's based on parameters passed to it. It declares fields for all the attributes it expects and then calls the Graph API's.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;The ANT build. &lt;/span&gt;&lt;br /&gt;I assume you have JMeter working from ANT, this assumes all the libraries needed for ANT and JMeter are in place&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&amp;lt;project name="Jmeter" basedir="." default="runOfflineGraph"&amp;gt;&lt;br /&gt;&amp;lt;property name="lib.dir" value="${basedir}/lib"/&amp;gt;&lt;br /&gt;&amp;lt;property name="report.dir" value="${basedir}/report"/&amp;gt;&lt;br /&gt;&amp;lt;property name="styles.dir" value="${basedir}/styles"/&amp;gt;&lt;br /&gt;&amp;lt;property name="export.dir" value="${basedir}/export"/&amp;gt;&lt;br /&gt;&amp;lt;property environment="env"/&amp;gt;&lt;br /&gt;&amp;lt;property name="jmeter.home.dir" value="${env.JMETER_HOME}"/&amp;gt;&lt;br /&gt;&amp;lt;property name="jfreechart.home.dir" value="${env.JFREECHART_HOME}"/&amp;gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;path id="run.classpath"&amp;gt;&lt;br /&gt;&amp;lt;fileset dir="${jmeter.home.dir}" includes="**/*.jar"/&amp;gt;&lt;br /&gt;&amp;lt;fileset dir="${jfreechart.home.dir}" includes="**/*.jar"/&amp;gt;&lt;br /&gt;&amp;lt;fileset dir="${lib.dir}" includes="*.jar"/&amp;gt;&lt;br /&gt;&amp;lt;/path&amp;gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&amp;lt;target name="clean"&amp;gt;&lt;br /&gt;&amp;lt;delete dir="${report.dir}" /&amp;gt;&lt;br /&gt;&amp;lt;delete dir="${export.dir}" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="init"&amp;gt;&lt;br /&gt;&amp;lt;mkdir dir="${report.dir}" /&amp;gt;&lt;br /&gt;&amp;lt;mkdir dir="${export.dir}" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="runJMeter" depends="init"&amp;gt;&lt;br /&gt;&amp;lt;taskdef&lt;br /&gt;    name="jmeter"&lt;br /&gt;classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/&amp;gt;&lt;br /&gt;&lt;b&gt;&amp;lt;taskdef name="aggregatechart" classname="org.md.jmeter.ant.AggregateGraphTask" classpathref="run.classpath"/&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;tstamp /&amp;gt;&lt;br /&gt;&amp;lt;property name="uniqueTStamp" value="${DSTAMP}${TSTAMP}" /&amp;gt;&lt;br /&gt;&amp;lt;property name="imageNamePrefix" value="AggregateChartThreshold-${uniqueTStamp}" /&amp;gt;&lt;br /&gt;&amp;lt;property name="jmeter.result.fileName" value="${run.test.report}-${uniqueTStamp}" /&amp;gt;&lt;br /&gt;&amp;lt;property name="jmeter.result.file" value="${report.dir}/${jmeter.result.fileName}.jtl" /&amp;gt;&lt;br /&gt;&amp;lt;jmeter&lt;br /&gt;    jmeterhome="${jmeter.home.dir}"&lt;br /&gt;    testplan="${run.test.plan}"&lt;br /&gt;        resultlog="${jmeter.result.file}"&amp;gt;&lt;br /&gt;    &amp;lt;property name="jmeter.save.saveservice.output_format" value="xml"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="run.threadcount" value="${run.threadcount}" /&amp;gt;&lt;br /&gt;    &amp;lt;property name="run.loopcount" value="${run.loopcount}" /&amp;gt;&lt;br /&gt;    &amp;lt;property name="sample_variables" value="${sample_variables}" /&amp;gt;&lt;br /&gt;&amp;lt;/jmeter&amp;gt;&lt;br /&gt;&amp;lt;xslt&lt;br /&gt;    in="${jmeter.result.file}"&lt;br /&gt;    out="${report.dir}/${jmeter.result.fileName}.html"&lt;br /&gt;    style="${styles.dir}/${xsl.file}"&amp;gt;&lt;br /&gt;    &amp;lt;param name="imageNamePrefix" expression="${imageNamePrefix}"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt; &amp;lt;aggregatechart jmeterHome="${jmeter.home.dir}" jmeterResultFile="${jmeter.result.file}" outputDir="${report.dir}"&lt;br /&gt;outputFilePrefix="${imageNamePrefix}" showThreshold="true" threshold="200"/&amp;gt;&lt;/b&gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="runOfflineGraph" depends="init"&amp;gt;&lt;br /&gt;&amp;lt;antcall target="runJMeter"&amp;gt;&lt;br /&gt;&amp;lt;param name="run.test.plan" value="OfflineGraphs.jmx"/&amp;gt;&lt;br /&gt;&amp;lt;param name="run.test.report" value="OfflineGraph"/&amp;gt;&lt;br /&gt;&amp;lt;param name="sample_variables" value=""/&amp;gt;&lt;br /&gt;&amp;lt;param name="run.threadcount" value="1"/&amp;gt;&lt;br /&gt;&amp;lt;param name="run.loopcount" value="5"/&amp;gt;&lt;br /&gt;&amp;lt;param name="xsl.file" value="OfflineGraph.xsl" /&amp;gt;&lt;br /&gt;&amp;lt;/antcall&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Important points are&lt;br /&gt;a) we define a run.classpath which has everything we need at runtime to generate the graphs.&lt;br /&gt;b) we have a taskdef aggregatechart for our custom task&lt;br /&gt;c) we invoke the custom chart by passing it the parameters we need. These are closely linked with the previous steps in the build. The result jog from jmeter  &lt;code&gt;(${jmeter.result.file}&lt;/code&gt;) is passed as an input to the task. The image file names to be generated are important&lt;code&gt; ${imageNamePrefix}&lt;/code&gt; as we need to reference this in the stylesheet.  The directory to which the Graph code writes must be the same as the XSLT output (or atleast the XSLT and Graph code must be consistent in where the images are referenced from in the HTML)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;The XSLT stylesheet&lt;/span&gt;&lt;br /&gt;The changes here are pretty straightforward. I've copied extras/jmeter-results-report_21.xsl and renamed it to OfflineGraph.xsl.&lt;br /&gt;The important changes are&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&amp;lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&amp;gt;&lt;br /&gt;&amp;lt;xsl:param name="imageNamePrefix"&amp;gt;AggregateChartThreshold&amp;lt;/xsl:param&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We pass in a parameter that is to be used while generating the img tag in the HTML&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;            &amp;lt;xsl:call-template name="summary" /&amp;gt;&lt;br /&gt;      &amp;lt;hr size="1" width="95%" align="left" /&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;xsl:call-template name="pagelist" /&amp;gt;&lt;br /&gt;      &amp;lt;hr size="1" width="95%" align="left" /&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;xsl:call-template name="detail" /&amp;gt;&lt;br /&gt;      &lt;b&gt;&amp;lt;xsl:call-template name="graph-images" /&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We call our custom template&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;            &amp;lt;th&amp;gt;&amp;lt;a href="#AverageGraph"&amp;gt;Average Time&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;&amp;lt;a href="#MinimumGraph"&amp;gt;Min Time&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;&amp;lt;a href="#MaximumGraph"&amp;gt;Max Time&amp;lt;/a&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We change the titles to be anchors (named anchors that are next to the images)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&amp;lt;xsl:template name="output-image"&amp;gt;&lt;br /&gt;&amp;lt;xsl:param name="suffix" /&amp;gt;&lt;br /&gt;&amp;lt;xsl:element name="img"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:attribute name="src"&amp;gt;&amp;lt;xsl:value-of select="$imageNamePrefix" /&amp;gt;-&amp;lt;xsl:value-of select="$suffix" /&amp;gt;.png&amp;lt;/xsl:attribute&amp;gt;&lt;br /&gt;&amp;lt;/xsl:element&amp;gt;&lt;br /&gt;&amp;lt;/xsl:template&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;xsl:template name="graph-images"&amp;gt;&lt;br /&gt;Graphs&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;Minimum&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;a name="MinimumGraph"&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;xsl:call-template name="output-image"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:with-param name="suffix"&amp;gt;Min&amp;lt;/xsl:with-param&amp;gt;&lt;br /&gt;&amp;lt;/xsl:call-template&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;Maximum&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;a name="MaximumGraph"&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;xsl:call-template name="output-image"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:with-param name="suffix"&amp;gt;Max&amp;lt;/xsl:with-param&amp;gt;&lt;br /&gt;&amp;lt;/xsl:call-template&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;Average&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;a name="AverageGraph"&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;xsl:call-template name="output-image"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:with-param name="suffix"&amp;gt;Avg&amp;lt;/xsl:with-param&amp;gt;&lt;br /&gt;&amp;lt;/xsl:call-template&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;Median&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;a name="MedianGraph"&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;xsl:call-template name="output-image"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:with-param name="suffix"&amp;gt;Median&amp;lt;/xsl:with-param&amp;gt;&lt;br /&gt;&amp;lt;/xsl:call-template&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;90 percentile&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;a name="NinetyPerGraph"&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;xsl:call-template name="output-image"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:with-param name="suffix"&amp;gt;90&amp;lt;/xsl:with-param&amp;gt;&lt;br /&gt;&amp;lt;/xsl:call-template&amp;gt;&lt;br /&gt;&amp;lt;/xsl:template&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Finally  we output img tags. The knowledge of how the Aggregate Graph generates the suffix for the images is hardcoded into the stylesheet. The passed parameter is used to form the filename as well (this is used to allow multiple runs , so that the images don't overwrite previous ones)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Running the ANT build&lt;/span&gt;&lt;br /&gt;This is the run.cmd I use (windows only)&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;&lt;br /&gt;set JAVA_HOME=C:\bea102\jdk150_11&lt;br /&gt;set JMETER_HOME=C:\projects\R1-Portal-CMS\test\jakarta-jmeter-2.3.4&lt;br /&gt;set JFREECHART_HOME=C:\work\java\jfreechart-1.0.13&lt;br /&gt;set ANT_HOME=C:\work\java\apache-ant-1.7.1&lt;br /&gt;set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%PATH%&lt;br /&gt;set CLASSPATH=%JMETER_HOME%\extras\ant-jmeter-1.0.9.jar;%CLASSPATH%&lt;br /&gt;ant %*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We set some environment properties that the build needs and run it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/graphs/graphWorkspace.zip"&gt;Source Code is available here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4625568230359482112?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4625568230359482112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4625568230359482112' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4625568230359482112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4625568230359482112'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/01/jmeter-graphs-and-ant.html' title='JMeter Graphs and ANT'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/S0uJJeumW9I/AAAAAAAAOso/rx57KmBM3Uw/s72-c/Load+Test+Results_1263241360515.png' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-6150225064737608860</id><published>2010-01-10T17:19:00.000-08:00</published><updated>2010-01-10T17:23:21.932-08:00</updated><title type='text'>Aggregate Graphs in JMeter using JFreeChart (3D Bar Charts) with thresholds</title><content type='html'>Borrowed heavily from the demos in JFreeChart, I've modified the previous samples to also support taking in a threshold value for response. Values less than the threshold are shown in Green Bars, values greater are shown using Red Bars. The threshold is also drawn.&lt;br /&gt;&lt;br /&gt;Sample Images&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/S0p9dSzksEI/AAAAAAAAOsg/GIOlM74GqAc/s1600-h/AggregateChartThreshold-Min.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/S0p9dSzksEI/AAAAAAAAOsg/GIOlM74GqAc/s320/AggregateChartThreshold-Min.png" alt="" id="BLOGGER_PHOTO_ID_5425286643339014210" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p9aQnKeGI/AAAAAAAAOsY/HGJ7-bnYWl8/s1600-h/AggregateChartThreshold-Median.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p9aQnKeGI/AAAAAAAAOsY/HGJ7-bnYWl8/s320/AggregateChartThreshold-Median.png" alt="" id="BLOGGER_PHOTO_ID_5425286591210485858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p9Wj2hFLI/AAAAAAAAOsQ/SjnaxKDsFmw/s1600-h/AggregateChartThreshold-Max.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p9Wj2hFLI/AAAAAAAAOsQ/SjnaxKDsFmw/s320/AggregateChartThreshold-Max.png" alt="" id="BLOGGER_PHOTO_ID_5425286527655679154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/S0p9TQBNRZI/AAAAAAAAOsI/toFL05DFXgo/s1600-h/AggregateChartThreshold-Avg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/S0p9TQBNRZI/AAAAAAAAOsI/toFL05DFXgo/s320/AggregateChartThreshold-Avg.png" alt="" id="BLOGGER_PHOTO_ID_5425286470792201618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/S0p9QDTShQI/AAAAAAAAOsA/gZx3PzvfqCw/s1600-h/AggregateChartThreshold-90.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/S0p9QDTShQI/AAAAAAAAOsA/gZx3PzvfqCw/s320/AggregateChartThreshold-90.png" alt="" id="BLOGGER_PHOTO_ID_5425286415838774530" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sample Code&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;    public static void writeAggregateChartWithThreshold() throws Exception {&lt;br /&gt;  File f = new File(JMETER_RESULT_FILE);&lt;br /&gt;  ResultCollector rc = new ResultCollector();&lt;br /&gt;  AggregateChartVisualizer v = new AggregateChartVisualizer(ConfigUtil&lt;br /&gt;          .getOutputGraphDir()&lt;br /&gt;          + "/AggregateChartThreshold",true,500);&lt;br /&gt;  ResultCollectorHelper rch = new ResultCollectorHelper(rc, v);&lt;br /&gt;  XStreamJTLParser p = new XStreamJTLParser(f, rch);&lt;br /&gt;  p.parse();&lt;br /&gt;  v.writeOutput();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/graphs/graphWorkspace.zip"&gt;Source code available here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-6150225064737608860?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/6150225064737608860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=6150225064737608860' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/6150225064737608860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/6150225064737608860'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/01/aggregate-graphs-in-jmeter-using_10.html' title='Aggregate Graphs in JMeter using JFreeChart (3D Bar Charts) with thresholds'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_AOk-4gocLaw/S0p9dSzksEI/AAAAAAAAOsg/GIOlM74GqAc/s72-c/AggregateChartThreshold-Min.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-5230234572851759689</id><published>2010-01-10T16:44:00.000-08:00</published><updated>2010-01-10T16:52:18.756-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Aggregate Graphs in JMeter using JFreeChart (3D Bar Charts)</title><content type='html'>Now written AggregateChartVisualizer which duplicates AggregateGraph functionality in JMeter.&lt;br /&gt;Sample Charts&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/S0p1NllnkVI/AAAAAAAAOr4/YYd3SOs4bbM/s1600-h/AggregateChart-Median.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/S0p1NllnkVI/AAAAAAAAOr4/YYd3SOs4bbM/s320/AggregateChart-Median.png" alt="" id="BLOGGER_PHOTO_ID_5425277577409827154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p1KWU6AVI/AAAAAAAAOrw/T5vXvX4PRZ8/s1600-h/AggregateChart-90.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p1KWU6AVI/AAAAAAAAOrw/T5vXvX4PRZ8/s320/AggregateChart-90.png" alt="" id="BLOGGER_PHOTO_ID_5425277521773592914" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/S0p1GPtK2eI/AAAAAAAAOro/my2nG7AFZk8/s1600-h/AggregateChart-Max.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/S0p1GPtK2eI/AAAAAAAAOro/my2nG7AFZk8/s320/AggregateChart-Max.png" alt="" id="BLOGGER_PHOTO_ID_5425277451276835298" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/S0p1CPVcK9I/AAAAAAAAOrg/6FBEVO7Em8o/s1600-h/AggregateChart-Avg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/S0p1CPVcK9I/AAAAAAAAOrg/6FBEVO7Em8o/s320/AggregateChart-Avg.png" alt="" id="BLOGGER_PHOTO_ID_5425277382457830354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p04okNkTI/AAAAAAAAOrY/4OZk7QI3lJw/s1600-h/AggregateChart-Min.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/S0p04okNkTI/AAAAAAAAOrY/4OZk7QI3lJw/s320/AggregateChart-Min.png" alt="" id="BLOGGER_PHOTO_ID_5425277217431982386" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sample Code to be used by clients&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;    public static void writeAggregateChart() throws Exception {&lt;br /&gt;       File f = new File(JMETER_RESULT_FILE);&lt;br /&gt;       ResultCollector rc = new ResultCollector();&lt;br /&gt;       AggregateChartVisualizer v = new AggregateChartVisualizer(ConfigUtil&lt;br /&gt;               .getOutputGraphDir()&lt;br /&gt;               + "/AggregateChart");&lt;br /&gt;       ResultCollectorHelper rch = new ResultCollectorHelper(rc, v);&lt;br /&gt;       XStreamJTLParser p = new XStreamJTLParser(f, rch);&lt;br /&gt;       p.parse();&lt;br /&gt;       v.writeOutput();&lt;br /&gt;   }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/graphs/graphWorkspace.zip"&gt;Source Code for the entire workspace available here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-5230234572851759689?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/5230234572851759689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=5230234572851759689' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5230234572851759689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5230234572851759689'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2010/01/aggregate-graphs-in-jmeter-using.html' title='Aggregate Graphs in JMeter using JFreeChart (3D Bar Charts)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_AOk-4gocLaw/S0p1NllnkVI/AAAAAAAAOr4/YYd3SOs4bbM/s72-c/AggregateChart-Median.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-7856378766833780484</id><published>2009-12-31T14:14:00.000-08:00</published><updated>2010-01-01T15:21:54.107-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Graphs for JMeter (parsing JMeter result logs)</title><content type='html'>One of the few features lacking in JMeter is when you run the tests from the command line, the out of box reports are restricted to a stylesheet that generates a summary report.&lt;br /&gt;There are workarounds, you could load the result into Excel (small files) , or you could parse the log file and use &lt;a href="http://www.jfree.org/jfreechart/"&gt;JFreeChart &lt;/a&gt;to generate the graphs which is what I did. See &lt;a href="#sample"&gt;examples&lt;/a&gt;&lt;br /&gt;The following is an explanation of the mechanisms I used. These are probably not going to be out of the box , but hopefully they will be useful to someone who can customise it. The samples are also meant to be used by developers, so if you are a Tester with little or no coding experience, get a developer from your team to help.&lt;br /&gt;&lt;br /&gt;I haven't looked closely at the JMeter parsing details, but you don't need to the details to use the JMeter classes (which in my opinion is a hallmark of a well designed system). There are two important files , the saveservice.properties and jmeter.properties which I have copied to a different location from the JMeter home so that I could modify them if I needed to.&lt;br /&gt;&lt;br /&gt;The basic code for parsing using JMeter classes(using the JMeter API) is&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;SaveService.loadTestResults(FileInputStream, ResultCollectorHelper);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;where ResultCollectorHelper is passed a &lt;a href="http://jakarta.apache.org/jmeter/api/org/apache/jmeter/visualizers/Visualizer.html"&gt;Visualizer&lt;/a&gt;. The Visualizer has one method that is important to us&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;add (SampleResult sampleResult)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The Visualizer interface is a simple strategy that can be implemented as we want. Since we also want to write some graphs, I created a new interface called OfflineVisualizer which adds a single method&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;public Object writeOutput() throws IOException&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Here is the class diagram (generated using &lt;a href="http://www.fujaba.de/"&gt;FUJABA&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/Sz54yE92v8I/AAAAAAAAOqQ/MomFyv5s1oc/s1600-h/JMeterGraph.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 167px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/Sz54yE92v8I/AAAAAAAAOqQ/MomFyv5s1oc/s320/JMeterGraph.png" alt="" id="BLOGGER_PHOTO_ID_5421903803122630594" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Visualizer is a simple strategy pattern. I've some sample implementations for LineChartVisualizer, StackedBarChartVisualizer, MinMaxAvgGraphVisualizer respectively to draw a line chart for each response, a Stacked chart (latency plus response) or a line chart showing Min,Max, Avg along with the response time.&lt;br /&gt;&lt;br /&gt;If we take a quick look at the LineChartVisualizer code , its pretty straightforward, it simply uses the JFreeChart API and populates the data from the SampleResult. Note that the line chart objects would use memory proportional to the number of samples&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;//adds a sample. JFreechart uses a TimeSeries object into which we set each data item&lt;br /&gt;public void add(SampleResult sampleResult) {&lt;br /&gt;String label = sampleResult.getSampleLabel();&lt;br /&gt;TimeSeries s1 = map.get(label);&lt;br /&gt;if (s1 == null) {&lt;br /&gt;   s1 = new TimeSeries(label);&lt;br /&gt;   map.put(label, s1);&lt;br /&gt;}&lt;br /&gt;long responseTime = sampleResult.getTime();&lt;br /&gt;Date d = new Date(sampleResult.getStartTime());&lt;br /&gt;s1.addOrUpdate(new Millisecond(d), responseTime);&lt;br /&gt;}&lt;br /&gt;//uses JFreeChartAPI to write the data into an image file&lt;br /&gt;public Object writeOutput() throws IOException {&lt;br /&gt;TimeSeriesCollection dataset = new TimeSeriesCollection();&lt;br /&gt;for (Map.Entry&amp;lt;String, TimeSeries&amp;gt; entry : map.entrySet()) {&lt;br /&gt;   dataset.addSeries(entry.getValue());&lt;br /&gt;}&lt;br /&gt;JFreeChart chart = createChart(dataset);&lt;br /&gt;FileOutputStream fos = null;&lt;br /&gt;try {&lt;br /&gt;   fos = new FileOutputStream(fileName);&lt;br /&gt;   ChartUtilities.writeChartAsPNG(fos, chart, WIDTH, HEIGHT);&lt;br /&gt;} finally {&lt;br /&gt;   if (fos != null) {&lt;br /&gt;       fos.close();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;return null;&lt;br /&gt;}&lt;br /&gt;//use the JFreeChart API to generate a Line Chart&lt;br /&gt;private static JFreeChart createChart(XYDataset dataset) {&lt;br /&gt;JFreeChart chart = ChartFactory.createTimeSeriesChart("Response Chart", // title&lt;br /&gt;       "Date", // x-axis label&lt;br /&gt;       "Time(ms)", // y-axis label&lt;br /&gt;       dataset, // data&lt;br /&gt;       true, // create legend?&lt;br /&gt;       true, // generate tooltips?&lt;br /&gt;       false // generate URLs?&lt;br /&gt;       );&lt;br /&gt;&lt;br /&gt;chart.setBackgroundPaint(Color.white);&lt;br /&gt;XYPlot plot = (XYPlot) chart.getPlot();&lt;br /&gt;plot.setBackgroundPaint(Color.lightGray);&lt;br /&gt;plot.setDomainGridlinePaint(Color.white);&lt;br /&gt;plot.setRangeGridlinePaint(Color.white);&lt;br /&gt;plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));&lt;br /&gt;plot.setDomainCrosshairVisible(true);&lt;br /&gt;plot.setRangeCrosshairVisible(true);&lt;br /&gt;XYItemRenderer r = plot.getRenderer();&lt;br /&gt;if (r instanceof XYLineAndShapeRenderer) {&lt;br /&gt;   XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;&lt;br /&gt;   renderer.setBaseShapesVisible(true);&lt;br /&gt;   renderer.setBaseShapesFilled(true);&lt;br /&gt;   renderer.setDrawSeriesLineAsPath(true);&lt;br /&gt;}&lt;br /&gt;DateAxis axis = (DateAxis) plot.getDomainAxis();&lt;br /&gt;axis.setDateFormatOverride(new SimpleDateFormat("dd-MMM-yyyy HH:mm"));&lt;br /&gt;return chart;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can change the data some graphs show by using the Decorator pattern. One decorator LabelFilterVisualizer is shown.&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;/**&lt;br /&gt;* decorates the visualizer by filtering out labels&lt;br /&gt;*/&lt;br /&gt;public void add(SampleResult sampleResult) {&lt;br /&gt; boolean allow = labels.contains(sampleResult.getSampleLabel());&lt;br /&gt; if (!pass) {&lt;br /&gt;     allow = !allow;&lt;br /&gt; }&lt;br /&gt; if (allow) {&lt;br /&gt;     visualizer.add(sampleResult);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* delegates to the decorated visualizer&lt;br /&gt;*&lt;br /&gt;* @return whatever the decorated visualizer returns&lt;br /&gt;*/&lt;br /&gt;public Object writeOutput() throws IOException {&lt;br /&gt; return visualizer.writeOutput();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This class filters out labels and only delegates those that satisfy the criteria. The writing of the image is delegated to the decorated OfflineVisualizer&lt;br /&gt;We can also use the composite pattern(CompositeVisualizer) to have multiple graphs generated with a single pass through the result log file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;/**&lt;br /&gt;* adds the sample to each of the composed visualizers&lt;br /&gt;*/&lt;br /&gt;public void add(SampleResult sampleResult) {&lt;br /&gt;  for (OfflineVisualizer visualizer : visualizers) {&lt;br /&gt;      visualizer.add(sampleResult);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* @return a List of each result from the composed visualizer&lt;br /&gt;*/&lt;br /&gt;public Object writeOutput() throws IOException {&lt;br /&gt;  List&amp;lt;Object&amp;gt; result = new ArrayList&amp;lt;Object&amp;gt;();&lt;br /&gt;  for (OfflineVisualizer visualizer : visualizers) {&lt;br /&gt;      result.add(visualizer.writeOutput());&lt;br /&gt;  }&lt;br /&gt;  return result;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally we can use all the above to process multiple files , for e.g. when we want to show trends across multiple runs with varying thread counts.&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;/**&lt;br /&gt;* parses each file&lt;br /&gt;*&lt;br /&gt;* @throws Exception&lt;br /&gt;*/&lt;br /&gt;public void parse() throws Exception {&lt;br /&gt;  // One day we might multithread this&lt;br /&gt;  for (String file : files) {&lt;br /&gt;      ResultCollector rc = new ResultCollector();&lt;br /&gt;      TotalThroughputVisualizer ttv = new TotalThroughputVisualizer();&lt;br /&gt;      visualizers.add(ttv);&lt;br /&gt;      ResultCollectorHelper rch = new ResultCollectorHelper(rc, ttv);&lt;br /&gt;      XStreamJTLParser p = new XStreamJTLParser(new File(file), rch);&lt;br /&gt;      p.parse();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Gets the resulting throughput from each file and combines them&lt;br /&gt;*&lt;br /&gt;* @return always returns null&lt;br /&gt;* @throws IOException&lt;br /&gt;*/&lt;br /&gt;public Object writeOutput() throws IOException {&lt;br /&gt;  XYSeries xyseries = new XYSeries("throughput");&lt;br /&gt;  for (AbstractOfflineVisualizer visualizer : visualizers) {&lt;br /&gt;      Throughput throughput = (Throughput) visualizer.writeOutput();&lt;br /&gt;      xyseries.add(throughput.getThreadCount(), throughput&lt;br /&gt;              .getThroughput());&lt;br /&gt;  }&lt;br /&gt;  XYSeriesCollection dataset = new XYSeriesCollection();&lt;br /&gt;  dataset.addSeries(xyseries);&lt;br /&gt;  JFreeChart chart = createChart(dataset);&lt;br /&gt;  FileOutputStream fos = null;&lt;br /&gt;  try {&lt;br /&gt;      fos = new FileOutputStream(fileName);&lt;br /&gt;      ChartUtilities.writeChartAsPNG(fos, chart, WIDTH, HEIGHT);&lt;br /&gt;  } finally {&lt;br /&gt;      if (fos != null) {&lt;br /&gt;          fos.close();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="sample"&gt;&lt;/a&gt;&lt;br /&gt;Here's a &lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/graphs/OfflineGraphs.jmx"&gt;sample&lt;/a&gt; that I ran. A single thread hits 3 pages on the apache website in a loop.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Sz1QZ5nbTbI/AAAAAAAAOjU/IoHdEPNQ-HQ/s1600-h/LineChart.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Sz1QZ5nbTbI/AAAAAAAAOjU/IoHdEPNQ-HQ/s320/LineChart.png" alt="" id="BLOGGER_PHOTO_ID_5421577932317085106" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Response times are plotted against each label (without considering the thread).&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;File f = new File(JMETER_RESULT_FILE);&lt;br /&gt;ResultCollector rc = new ResultCollector();&lt;br /&gt;LineChartVisualizer v = new LineChartVisualizer(OUTPUT_GRAPH_DIR + "/LineChart.png");&lt;br /&gt;ResultCollectorHelper rch = new ResultCollectorHelper(rc, v);//this is the visualizer we want&lt;br /&gt;XStreamJTLParser p = new XStreamJTLParser(f, rch);&lt;br /&gt;p.parse();&lt;br /&gt;v.writeOutput(); //write the output&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The next example filters out only the Component reference request and plots the response time, the minimum time, the maximum time and the average time for this request. You could extend this to indicate the median or the 90th percentile.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/Sz1Q9hiO9fI/AAAAAAAAOjc/TJsIzjZ7LZc/s1600-h/MinMaxAvg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/Sz1Q9hiO9fI/AAAAAAAAOjc/TJsIzjZ7LZc/s320/MinMaxAvg.png" alt="" id="BLOGGER_PHOTO_ID_5421578544328144370" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The code for this graph is&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;File f = new File(JMETER_RESULT_FILE);&lt;br /&gt;ResultCollector rc = new ResultCollector();&lt;br /&gt;MinMaxAvgGraphVisualizer v = new MinMaxAvgGraphVisualizer(OUTPUT_GRAPH_DIR + "/MinMaxAvg.png");&lt;br /&gt;String[] labels = {"Component reference"}; //we only want this label&lt;br /&gt;LabelFilterVisualizer lv= new  LabelFilterVisualizer(Arrays.asList(labels), v);//decorate the MinMaxAvgGraphVisualizer&lt;br /&gt;ResultCollectorHelper rch = new ResultCollectorHelper(rc, lv);//use the decorated visualizer&lt;br /&gt;XStreamJTLParser p = new XStreamJTLParser(f, rch);&lt;br /&gt;p.parse();&lt;br /&gt;lv.writeOutput();//write it out&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The next chart shows a stacked chart which splits the response time for the Component reference into latency and the rest of the time.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/Sz1RXoOFmRI/AAAAAAAAOjk/xXgRSOOsAgI/s1600-h/StackedBarChart.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/Sz1RXoOFmRI/AAAAAAAAOjk/xXgRSOOsAgI/s320/StackedBarChart.png" alt="" id="BLOGGER_PHOTO_ID_5421578992799291666" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;File f = new File(JMETER_RESULT_FILE);&lt;br /&gt;ResultCollector rc = new ResultCollector();&lt;br /&gt;StackedBarChartVisualizer v = new StackedBarChartVisualizer(OUTPUT_GRAPH_DIR + "/StackedBarChart.png");&lt;br /&gt;String[] labels = {"Component reference"};//we only want this label&lt;br /&gt;LabelFilterVisualizer lv= new  LabelFilterVisualizer(Arrays.asList(labels), v);//Decorate the StackedBarChartVisualizer&lt;br /&gt;ResultCollectorHelper rch = new ResultCollectorHelper(rc, lv);&lt;br /&gt;XStreamJTLParser p = new XStreamJTLParser(f, rch);&lt;br /&gt;p.parse();&lt;br /&gt;lv.writeOutput(); //write the output&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We could also run all these graphs at the same time using the Composite&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;File f = new File(JMETER_RESULT_FILE);&lt;br /&gt;ResultCollector rc = new ResultCollector();&lt;br /&gt;LineChartVisualizer lcv = new LineChartVisualizer(OUTPUT_GRAPH_DIR + "/AllLineChart.png");&lt;br /&gt;StackedBarChartVisualizer sbv = new StackedBarChartVisualizer(OUTPUT_GRAPH_DIR + "/AllStackedBarChart.png");&lt;br /&gt;MinMaxAvgGraphVisualizer mmav = new MinMaxAvgGraphVisualizer(OUTPUT_GRAPH_DIR + "/AllMinMaxAvg.png");&lt;br /&gt;String[] labels = {"Component reference"};&lt;br /&gt;LabelFilterVisualizer lv= new  LabelFilterVisualizer(Arrays.asList(labels), sbv);//decorate&lt;br /&gt;LabelFilterVisualizer lv2= new  LabelFilterVisualizer(Arrays.asList(labels), mmav);//decorate&lt;br /&gt;OfflineVisualizer[] vs = {lcv, lv,lv2};//use these 3 visualizers&lt;br /&gt;CompositeVisualizer cv = new CompositeVisualizer(Arrays.asList(vs));//create a composite&lt;br /&gt;ResultCollectorHelper rch = new ResultCollectorHelper(rc, cv);&lt;br /&gt;XStreamJTLParser p = new XStreamJTLParser(f, rch);&lt;br /&gt;p.parse();&lt;br /&gt;cv.writeOutput();//the composite will delegate to each visualizer&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I also reran the same test for 1, 3,5,7 and 10 threads. Using the classes above and a new throughput visualizer (where I calculate throughput as total number of requests / total time the test ran) and plotted the throughput v/s the number of threads&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Sz1SRifzrrI/AAAAAAAAOjs/8pC2FZQ_gNM/s1600-h/Throughput.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Sz1SRifzrrI/AAAAAAAAOjs/8pC2FZQ_gNM/s320/Throughput.png" alt="" id="BLOGGER_PHOTO_ID_5421579987695414962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="source-code"&gt;&lt;code&gt;String [] files = {JMETER_RESULT_DIR + "/OfflineGraphs-dev-200912311310.jtl", JMETER_RESULT_DIR + "/OfflineGraphs-dev-200912311312.jtl",JMETER_RESULT_DIR + "/OfflineGraphs-dev-200912311315.jtl",JMETER_RESULT_DIR + "/OfflineGraphs-dev-200912311316.jtl",JMETER_RESULT_DIR + "/OfflineGraphs-dev-200912311318.jtl"};&lt;br /&gt;MultiFileThroughput mft = new MultiFileThroughput(Arrays.asList(files),OUTPUT_GRAPH_DIR + "/Throughput.png");&lt;br /&gt;mft.parse();&lt;br /&gt;mft.writeOutput();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above examples are not exhaustive and probably wont work for you (for e.g. threads are ignored, thread groups are ignored, and these might have meaning for your test). However you should be able to use this to write your own implementation.&lt;br /&gt;&lt;br /&gt;Running the code.&lt;br /&gt;a.  Download the &lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/graphs/graphWorkspace.zip"&gt;code&lt;/a&gt;. This is an eclipse workspace. To get this to compile, you need to define two variables in eclipse (JMETER_HOME and JFREECHART_HOME) for the classpath. Modify config.properties to whatever is applicable for your system. Use GraphClient to see the samples&lt;br /&gt;I created an additional dummy directory for Jmeter home and created a bin directory under it and copied jmeter.properties and saveservice.properties.&lt;br /&gt;b. Change the client to use the visualizers you want. The sample client should give you some idea. Or create a new visualizer&lt;br /&gt;c. Compile and run! If you use a different IDE or want to use ANT it should be pretty straight forward. The source code has been written and tested on Java 1.5 . There isn't any 1.5 feature I use except generics and the new for loop syntax. You could change this to be 1.4 compatible.&lt;br /&gt;&lt;br /&gt;Further work&lt;br /&gt;a. Combining results from multiple files into a single run.&lt;br /&gt;b. Making the visualizers configurable&lt;br /&gt;c. Canned HTML reports&lt;br /&gt;d. Threads/ThreadGroups&lt;br /&gt;e. Determine limits for the graphs.&lt;br /&gt;f. Support custom attributes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If there are specific graph requests , I might take a look into it, day job and wife willing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-7856378766833780484?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/7856378766833780484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=7856378766833780484' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/7856378766833780484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/7856378766833780484'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/12/graphs-for-jmeter-parsing-jmeter-result.html' title='Graphs for JMeter (parsing JMeter result logs)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_AOk-4gocLaw/Sz54yE92v8I/AAAAAAAAOqQ/MomFyv5s1oc/s72-c/JMeterGraph.png' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2260655799138140053</id><published>2009-12-16T12:43:00.001-08:00</published><updated>2009-12-16T15:05:22.474-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>JMeter and SLA's</title><content type='html'>One of the current issues on our site is that while we profiled and performance and load tested the important pages before we went live, we haven't done it for subsequent builds and releases. There are various excuses for this (lack of time, lack of representative environments, restrictions on the actions that may be performed because the site is live), none of them really justified. However no matter how much you test the site before hand, the site may still malfunction, perhaps transiently on production. For e.g. we sometimes got timeout errors between 6:00 to 10:00 a.m. (it was eventually determined to be a Database index compacting job that was creating trouble). The problem is that we had to be reactive, look at the logs, there was a timeout, run around like headless chickens because the site was working fine now, no access to the environment to see whats happening etc. Now we could have configured logs to automatically notify us when there are errors but this would only work if there was a timeout (in our 60 seconds for any remote operation). If a page that normally takes 2 seconds to load took anything under 60 seconds we would not see errors.&lt;br /&gt;In previous projects , we had OVIS, which I believe is expensive, but my current project has no such commerical tool. Open source tools all seem to solve parts of the problem , but there didn't seem to be any tool that did everything I wanted.&lt;br /&gt;Briefly&lt;br /&gt;a. Flexible schemes to measure response times. We needed to be able to simulate accessing stand alone urls, login flows, checkout flows, search flows.&lt;br /&gt;b. Ability to store the data and view trend graphs&lt;br /&gt;c. Ability to run the tests on a schedule&lt;br /&gt;d. Ability to specify thresholds for each page (again with a fair degree of flexibility) and mark responses as failed&lt;br /&gt;e. Flexible notification schemes&lt;br /&gt;&lt;br /&gt;The choice of technologies I used were based more on things I wanted to learn or refresh rather than the best there is, so keep in mind this is more of a toy than I would have liked&lt;br /&gt;a. JMeter for response times. I'm not really interested in loading the site, nor do I want exact browser render times, I'm just looking for ballpark numbers and deviations, especially after builds or at odd hours.&lt;br /&gt;b. Hudson for scheduling Jmeter builds. I chose hudson because I haven't used it before.&lt;br /&gt;c. STAX for parsing JTL. I chose stax because I wanted to be able to parse large files, and i already know SAX , but I've never used STAX.&lt;br /&gt;d. Tomcat with JSP + Spring. I've loved Spring JDBC ever since I've used it (take that Hibernate, JPA, JDO, EJB). It removes all the redundant code while not sacrificing the power of SQL , and there is no learning curve beyond Spring. I chose JSP over any of the MVC framework because of shortage of time. While people may insist how their preferred framework saves them tons of time , this only applies in the long run&lt;br /&gt;e. JQuery for all the javascript stuff&lt;br /&gt;f. JFreeChart for the chart related functionality. I've used this before and found it to be a solid library.&lt;br /&gt;g. Derby for the database, this is something I have not used before,  I wanted a reasonably stable database , non embedded.&lt;br /&gt;&lt;br /&gt;Most of the things Ive written aren't really reusable, in addition this was quick and dirty, so don't expect this to work for you&lt;br /&gt;a. The JMeter Script&lt;br /&gt;b. Parsing the JMeter Script and loading it into the database&lt;br /&gt;c. Scheduling JMeter to run in Hudson&lt;br /&gt;d. Writing a UI around this&lt;br /&gt;e. Allowing administrators to configure thresholds and notifications&lt;br /&gt;f. Notifications&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2260655799138140053?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2260655799138140053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2260655799138140053' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2260655799138140053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2260655799138140053'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/12/jmeter-and-slas.html' title='JMeter and SLA&apos;s'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4391325158493275650</id><published>2009-11-20T19:59:00.001-08:00</published><updated>2009-11-22T11:51:44.593-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Randomly Clicking links in JMeter (sometimes known as spidering)</title><content type='html'>A follow up to &lt;a href="http://theworkaholic.blogspot.com/2009/10/spidering-site-with-jmeter.html"&gt;Spidering a site with JMeter&lt;/a&gt;&lt;br /&gt;A user on the JMeter mailing list posted his solution using the HTML link parser[1] to spider a site. The spidering consists of clicking a link at random from the links parsed from the last accessed page.&lt;br /&gt;The test looks like&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/SwdmxAh8Y5I/AAAAAAAAOCs/Egnqkb3kCng/s1600/RandomClicks.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 229px; height: 242px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/SwdmxAh8Y5I/AAAAAAAAOCs/Egnqkb3kCng/s320/RandomClicks.jpg" alt="" id="BLOGGER_PHOTO_ID_5406402869823562642" border="0" /&gt;&lt;/a&gt;Script available at&lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/self.aspx/Public/jmeter/spider/Spider.jmx"&gt; Spider.jmx&lt;/a&gt;&lt;br /&gt;The Initial Request is used by the HTML Link Parser to get the initial set of urls from which one will be chosen.&lt;br /&gt;The While controllers condition is simply true , since we want it to loop forever.&lt;br /&gt;The Spider HTTP Sampler has a path of .*.&lt;br /&gt;The If Controller has a condition ${__javaScript(!${JMeterThread.last_sample_ok})}&lt;br /&gt;This simply checks if the last sample fetched failed (by .* or because it fetched a CGI/PDF which cant be parsed for links and if so reexecutes the Initial Request.)&lt;br /&gt;There are numerous tweaks you can implement , you might not execute the initial request, it might be one at random that you pick , or the last successful request. You might choose to check the request being made to restrict the paths.&lt;br /&gt;&lt;br /&gt;Note that this clicks a link at random from a set of links acquired from the previously clicked page. This cannot ensure that a link is not repeated and cannot ensure that all links are fetched.&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTML_Link_Parser"&gt;http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTML_Link_Parser&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4391325158493275650?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4391325158493275650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4391325158493275650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4391325158493275650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4391325158493275650'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/11/randomly-clicking-links-in-jmeter.html' title='Randomly Clicking links in JMeter (sometimes known as spidering)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_AOk-4gocLaw/SwdmxAh8Y5I/AAAAAAAAOCs/Egnqkb3kCng/s72-c/RandomClicks.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2152043749271511093</id><published>2009-11-11T13:58:00.000-08:00</published><updated>2009-11-20T20:25:16.453-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Dependent tests in JMeter (kind of)</title><content type='html'>A common use case in testing is the concept of dependent tests(except for the unit test fanatics who love JUnit and didn't realise they needed this functionality till TestNG came along). One of the requirements then becomes that these dependent test should not execute if the test that it depends on fails. To implement this in JMeter we need to use the following two pieces of information&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;  The variable  &lt;/span&gt;&lt;b style="font-weight: bold; font-style: italic;"&gt; JMeterThread.last_sample_ok &lt;/b&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;  is set to  "true" or "false" after all assertions for a sampler have been run. [1]&lt;br /&gt;If Controller -Evaluate for all children - Should condition be evaluated for all children? If not checked, then the condition is only evaluated on entry.[2]&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Combining the two bits of information we have&lt;br /&gt;Thread Group&lt;br /&gt; If Controller((${JMeterThread.last_sample_&lt;div id=":79" class="ii gt"&gt;ok}) with Evaluate for all children = checked&lt;br /&gt;    Req 1 --&gt; if this errors req 1 and req 2 wont be executed&lt;br /&gt;    Req 2 --&gt; if this errors , req 3 wont be executed&lt;br /&gt;    Req 3&lt;br /&gt;Note that any assertion failing would also mark the request as failed.&lt;br /&gt;Note also that you cannot have nested dependent sets but you could flatten them out as separate IF controllers.&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;[1] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#assertions"&gt;http://jakarta.apache.org/jmeter/usermanual/component_reference.html#assertions&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#If_Controller"&gt;http://jakarta.apache.org/jmeter/usermanual/component_reference.html#If_Controller&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2152043749271511093?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2152043749271511093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2152043749271511093' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2152043749271511093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2152043749271511093'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/11/dependent-tests-in-jmeter-kind-of.html' title='Dependent tests in JMeter (kind of)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2300590401901963741</id><published>2009-10-30T09:11:00.000-07:00</published><updated>2009-11-07T11:44:18.007-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance Tuning'/><category scheme='http://www.blogger.com/atom/ns#' term='Code'/><title type='text'>Commenting Code</title><content type='html'>Have you ever written code that reads from a BufferedReader? Suppose you read someone else's code that said&lt;br /&gt;&lt;br /&gt;//There is a BufferedReader r&lt;br /&gt;     &lt;blockquote&gt;StringBuffer sb = new StringBuffer();&lt;br /&gt;     int i;&lt;br /&gt;     while ((i = r.read()) != -1)&lt;br /&gt;             sb.append((char)i);&lt;/blockquote&gt;&lt;br /&gt;What do you think ? will you change it to the more normal&lt;br /&gt;     &lt;blockquote&gt;        int i;&lt;br /&gt;char[] data = new char[1024];&lt;br /&gt;&lt;code&gt;&lt;b&gt;&lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/BufferedReader.html#read%28char%5B%5D,%20int,%20int%29"&gt;&lt;/a&gt;&lt;/b&gt;&lt;/code&gt;        while ((i = r.read(data,0,data.length)) != -1)&lt;br /&gt;             sb.append(data);&lt;br /&gt;Edit: Embarassingly the above code is wrong, but the code is only illustrative , reading a character at a time v/s reading chunks of it&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Which is more efficient? Which is more 'performant'?&lt;br /&gt;&lt;br /&gt;And finally if you read the original code  with an additional comment&lt;br /&gt;&lt;br /&gt;     &lt;blockquote&gt;StringBuffer sb = new StringBuffer();&lt;br /&gt;     int i;&lt;br /&gt;     // under JIT, testing seems to show this simple loop is as fast&lt;br /&gt;     // as any of the alternatives&lt;br /&gt;     while ((i = r.read()) != -1)&lt;br /&gt;             sb.append((char)i);&lt;/blockquote&gt;would you even bother?&lt;br /&gt;&lt;br /&gt;Code snippet taken from ImportSupport.java - jakarta-taglibs-standard-1.1.2-src.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2300590401901963741?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2300590401901963741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2300590401901963741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2300590401901963741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2300590401901963741'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/commenting-code.html' title='Commenting Code'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2262180110167332979</id><published>2009-10-29T22:54:00.000-07:00</published><updated>2009-12-20T14:17:29.514-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Spidering a site with JMeter</title><content type='html'>Sometimes we need to check every link on the site and see that they all work, and this question came up a couple of times on the JMeter forum &lt;span style="font-style: italic;"&gt;'How do I use JMeter to spider my site?'&lt;/span&gt;&lt;br /&gt;But before we go into the solutions, lets take a step back and see the reasons behind wanting to spider the site or &lt;a href="http://theworkaholic.blogspot.com/2009/10/spidering-site-with-jmeter.html#solution"&gt;skip to solution&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;a. You want to find out whether any urls respond with a 404. This isn't really a task for JMeter and there are various open source/free link checkers that one might use so there really isn't a need to run JMeter to solve this class of problems  (&lt;a href="http://java-source.net/open-source/crawlers"&gt;http://java-source.net/open-source/crawlers&lt;/a&gt; for just spiders in Java. There  are others too like &lt;a href="http://home.snafu.de/tilman/xenulink.html"&gt;Xenu&lt;/a&gt; or &lt;a href="http://linkchecker.sourceforge.net/"&gt;LinkChecker&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;b. You want to generate some sort of background load and you hit upon this technique. A spider run with a specific number of threads will provide the load. While a valid scenario, this doesn't really simulate what the users are doing on the site. So it goes back to what are you trying to simulate?. It's much better to simulate actual journeys with representative loads. You might need to study your logs and your webserver monitoring tools to figure this out. It's tougher to do this, but it's more useful.&lt;br /&gt;&lt;br /&gt;c. You want to simulate the behavior of an actual spider (like Google) and see how your site responds, whether all the pages are reachable. See a.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other problems&lt;/span&gt;&lt;br /&gt;A test without assertions is pretty much useless. A spidering test by its nature is difficult to assert (other than response code = 200! and perhaps the page does not contain the standard error message shown).&lt;br /&gt;&lt;br /&gt;JMeter does not really provide good out of the box support for spidering. The documents refer to an HTML Link Parser which can be used for spiders which leads some users to try it out and complain that it doesn't work. It does(&lt;a href="http://theworkaholic.blogspot.com/2009/11/randomly-clicking-links-in-jmeter.html"&gt;see this post&lt;/a&gt;) but not how you expect, and not as a spider (The reference manual needs to change).&lt;br /&gt;&lt;br /&gt;Before we go on to trying to implement an actual Spider in JMeter, lets see some alternatives that we have (using JMeter and not a third party tool).&lt;br /&gt;a. Most sites have a fixed set of URL's and a possible dynamic set e.g. a Product Catalog  where each product maps to a row in the database. It is easy enough to write a query that fetches these (using a JDBC Sampler) and generating a CSV file that contains the URL's you want. The JDBC sampler is followed by a Thread Group (number of threads the spider will run) which reads each URL from the CSV. This is especially useful when you consider that it is quite possible that some links are not accessible from any other link in the site (This is bad site design, but exists , for e.g. FAQ are not browsable on my current site, they must be searched for which means that there is no URL from which the FAQ is linked to and a spider would never find them directly)&lt;br /&gt;&lt;br /&gt;b. Some sites generate a sitemap (it may even be a sitemap that is used for Google) for the reasons mentioned above. It is trivial to parse this to obtain all the urls. A stylesheet can convert this into a CSV and the rest is the same as point a.&lt;br /&gt;&lt;br /&gt;One last thing before we start discussing JMeter solutions. The first time I came to know anything about how spiders work is when I ran &lt;a href="http://lucene.apache.org/nutch/"&gt;Nutch &lt;/a&gt;locally(and later refined with the knowledge of MapReduce).&lt;br /&gt;In a simplified form&lt;br /&gt;a. A first stage reads URLs that are pending from the buffer/queue and downloads the content. This is multithreaded but not too much so as to not bring down the site.&lt;br /&gt;b. The second stage parses the contents for links and feeds it into the same buffer and queue.&lt;br /&gt;c. A third stage indexes the content for search. This is irrelevant for our tests.&lt;br /&gt;A related concept is that of depth. i.e. In how many clicks(minimum)  does it take to reach the link from the root/home/starting point of the website.&lt;br /&gt;&lt;a name="solution"&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Attempt 1.&lt;/span&gt;&lt;br /&gt;Using the previous depth definition, most sites(because of menu's and sitemaps) need at the most 5-7 clicks to reach any page from the root page (kind of like Kevin Bacon's six degrees of separation).  This implies that instead of a generic solution we could have a hardcoded solution which fixes the depth that we look at and use the time tested method of Copy - Paste.&lt;br /&gt;Here's what this solution would like&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/SvULSYd_lTI/AAAAAAAAOBg/Nbr9AkuCQaM/s1600-h/CopyPasteSpider.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 117px; height: 320px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/SvULSYd_lTI/AAAAAAAAOBg/Nbr9AkuCQaM/s320/CopyPasteSpider.jpg" alt="" id="BLOGGER_PHOTO_ID_5401235738534581554" border="0" /&gt;&lt;/a&gt;The test plan is configured to run the Thread Groups serially&lt;br /&gt;1. Thread Group &lt;span style="font-weight: bold;"&gt;L0&lt;/span&gt; fetches all the urls listed in a file named L_0.csv. Each request is attached to beanshell listener which parses the response to extract all anchors and writes these anchors to a separate temp file. The code which does this is lifted from AnchorModifier and is accessed via a Beanshell script calling a Java class(&lt;a href="http://theworkaholic.blogspot.com/2009/10/spidering-site-with-jmeter.html#JMeterSpiderUtil"&gt;JMeterSpiderUtil&lt;/a&gt;).&lt;br /&gt;2. Thread Group &lt;span style="font-weight: bold;"&gt;L0 Consolidate&lt;/span&gt; (single thread) creates a unique set of all the urls from the temporary files created in step 1 and subtracts the urls already fetched from L_0.csv and writes these urls to a file named L_1.csv. This code is also in the Java class and is described below.&lt;br /&gt;3.  Thread Group &lt;span style="font-weight: bold;"&gt;L1&lt;/span&gt; (multi thread) fetches all the urls listed in the file L_1.csv which was created in step. Each request is attached to beanshell listener which parses the response to extract all anchors and writes these anchors to a separate temp file.&lt;br /&gt;4. Thread Group &lt;span style="font-weight: bold;"&gt;L1 Consolidate&lt;/span&gt; (single thread) creates a unique set of all the urls from the temporary files created in step 3 and subtracts the urls already fetched from L_0.csv,L_1.csv and writes these urls to a file named L_2.csv&lt;br /&gt;... and so on for any number of levels/depths that you want.&lt;br /&gt;If you are any sort of developer , you are probably groaning at the above. "Hasn't this guy heard about loops? What about maintaining these tests? Are we going to make any changes in 5 places ?".&lt;br /&gt;We could use Module Controllers to reuse most of the test structure but it's still inelegant.&lt;br /&gt;One of the reasons I've described the above is that even if the solution looks inelegant it is easy to understand and doesn't take time to implement, which means you can start testing your site pretty quickly. Note that your priority is the testing of the site , not the elegance of the testing script.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Attempt 2&lt;/span&gt;&lt;br /&gt;Lets now see if we can increase the elegance of the script. One of the problems we run into is that the CSV data set config can't use variable names for the filename. Another problem is that in the solution above we run the Thread Groups serially and we use a single thread in a thread group to combine the results. If we want to use a single looped thread group we have to ensure only 1 thread does the combining which needs to wait for all the other threads to complete. You can probably simplify this solution by extending the CSV data set config or the looping controllers, I don't consider these approaches because I have no Swing experience at all , so the only ways I extend JMeter are via BeanShell or Java.&lt;br /&gt;After some experimentation this is the solution that I've come up with&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/SvUOK1VmugI/AAAAAAAAOBo/Vk87MNZdONQ/s1600-h/LoopedSpider.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 172px; height: 320px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/SvUOK1VmugI/AAAAAAAAOBo/Vk87MNZdONQ/s320/LoopedSpider.jpg" alt="" id="BLOGGER_PHOTO_ID_5401238907379956226" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;1. The Loop Controller controls the depth/level&lt;br /&gt;2. The simple controller has an If controller that is only true for the thread with threadnumber 1. It defines the current level and copies the file L_${currentlevel}.csv to urls.csv&lt;br /&gt;3. The wait for everyone is configured with a synchronizing timer (same as total number of threads in a threadgroup) so that all the threads are waiting till the first thread has finished in step 2&lt;br /&gt;4. The while controller iterates over all the urls in the csv. The CSV Data Set is configured to read the copied urls.csv file (since we cannot make the name variable). What we will do in the subsequent steps is recreate this same file with new data. Each request is attached to beanshell listener which parses the response to extract all anchors and writes these anchors to a separate temp file. The code which does this is lifted from AnchorModifier and is accessed via a Beanshell script calling a Java class(&lt;a href="http://theworkaholic.blogspot.com/2009/10/spidering-site-with-jmeter.html#JMeterSpiderUtil"&gt;JMeterSpiderUtil&lt;/a&gt;).&lt;br /&gt;5. We have a copy of step 2 here, all the threads wait till everyone else is done (for that level only)&lt;br /&gt;6.  The If controller ensures that the consolidation is done only for the first thread, all the files written in step 4 are combined into a unique set, all the urls already processed are subtracted and a new file L_${nextlevel}.csv is written. Properties are set so that the ${currentlevel} now is the ${nextlevel} so that step 1 will now pick up this new file and copy it as urls.csv for the CSVDataSetConfig to pick up.&lt;br /&gt;7. The Reset Property Bean Shell sampler is used to reset the CSV Data Set Config&lt;br /&gt;FileServer server = FileServer.getFileServer(); // get the File Server&lt;br /&gt;server.closeFiles(); // close everything&lt;br /&gt;server.reserveFile("../spider/urls/urls.csv", null, "../spider/urls/urls.csv"); //reregister the CSV, we have chosen sharing mode as All Threads to avoid copying the alias name generation in CSVDataSet.java&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This was run with a root of http://jakarta.apache.org/jmeter/index.html.&lt;br /&gt;Only urls with jmeter in them were spidered and with the jakarta.apache.org host.&lt;br /&gt;Level 1 - 17 urls&lt;br /&gt;Level 2 - 29 urls&lt;br /&gt;Level 3 - 125 urls&lt;br /&gt;Level 4 - 833 urls&lt;br /&gt;Level 5 - 2 urls&lt;br /&gt;Level 6 - 0 urls&lt;br /&gt;And I did get some failures too e.g.&lt;br /&gt;http://jakarta.apache.org/jmeter/$next&lt;br /&gt;http://jakarta.apache.org/jmeter/$prev&lt;br /&gt;So I guess the test is successful because it found some issues!.&lt;br /&gt;Which means there are no more urls that satisfy our criteria. You could change the loop to a while controller and use this condition to check whether or not the test should exit. However some sites generate unique urls (e.g. by appending a timestamp) which makes it possible that your test might not exit , so you should normally have a safety for maximum depth.&lt;br /&gt;&lt;br /&gt;Is attempt 2 more elegant? Probably , but also less configurable and took about 2-3 days to get it working and needed some study of JMeter source code.  Note that the previous solution could vary the number of threads available to each Thread Group but this can't. However by using the constant throughput timer , you can achieve variable throughput for different levels.&lt;br /&gt;&lt;br /&gt;&lt;a name="JMeterSpiderUtil"&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;JMeterSpiderUtil.java&lt;/span&gt;&lt;br /&gt;The major part of this code is from AnchorModifier&lt;br /&gt;Important snippets are shown&lt;br /&gt;if(isExcluded(fetchedUrl) ) //excludes stuff like PDF/.jmx files which cant be parsed&lt;br /&gt;...&lt;br /&gt;(Document) HtmlParsingUtils&lt;br /&gt;     .getDOM(responseText.substring(index)); // gets a DOM from the request&lt;br /&gt;...&lt;br /&gt;NodeList nodeList = html.getElementsByTagName("a"); //gets the links&lt;br /&gt;...&lt;br /&gt;HTTPSamplerBase newUrl = HtmlParsingUtils.createUrlFromAnchor( hrefStr, ConversionUtils.makeRelativeURL(result .getURL(), base)); //get the url&lt;br /&gt;... &lt;br /&gt;     if(allowedHost.equalsIgnoreCase(newUrl.getDomain())) {&lt;br /&gt;         String currUrl = newUrl.getUrl().toString();&lt;br /&gt;         if(matchesPath(currUrl)) {&lt;br /&gt;             //currUrl = stripSessionId(currUrl);&lt;br /&gt;             //currUrl = stripTStamp(currUrl);&lt;br /&gt;             fw.write(currUrl + "\n");&lt;br /&gt;         }     &lt;br /&gt;     }&lt;br /&gt;//checks whether the host is the one we are interested in, whether the path is one that we want to spider, could strip out session ids or timestamp parameters in the url&lt;br /&gt;...&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/browse.aspx/Public/jmeter/spider?uc=4"&gt;Download Code&lt;/a&gt;&lt;br /&gt;SpiderTest - Attempt 1.&lt;br /&gt;SpiderTest2 - Attempt 2.&lt;br /&gt;JMeterSpiderUtil - Java utility.&lt;br /&gt;&lt;br /&gt;If you want to use the code&lt;br /&gt;a. Ensure that the total number of Threads is specified correctly in both synchronizing timers (use a property)&lt;br /&gt;b. Some directories are hardcoded. I used a directory named scripts under jmeter home, another directory called spider at the same level as scripts. Scripts has two sub directories temp and urls. L_0.csv the starting point is copied into urls.&lt;br /&gt;c. If you want to rerun the test ensure you delete all directories under temp and all previously generated csv files in urls (except for L_0.csv.&lt;br /&gt;d. You might have to change the java code to further filter urls /improve the code. The Jmeter path regular expression is hardcoded&lt;br /&gt;e. You have to change the allowedHost , probably to an allowable list rather than a single value.&lt;br /&gt;f. You probably have to honor robots.txt&lt;br /&gt;g. You might want to check the fetch embedded resources or change what urls are considered to be fetched (currently only anchors no forms or ajax urls based on a pattern)&lt;br /&gt;&lt;br /&gt;Note that the code is extremely inefficient and was only written to check if what I theorized in &lt;a href="http://www.mail-archive.com/jmeter-user@jakarta.apache.org/msg27108.html"&gt;http://www.mail-archive.com/jmeter-user@jakarta.apache.org/msg27108.html&lt;/a&gt; was possible&lt;br /&gt;There is a lot of work to properly parameterise this test , but hopefully this can get you started.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-1bd02fe33f80b8ac.skydrive.live.com/browse.aspx/Public/jmeter/spider"&gt;Code available here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2262180110167332979?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2262180110167332979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2262180110167332979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2262180110167332979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2262180110167332979'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/spidering-site-with-jmeter.html' title='Spidering a site with JMeter'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_AOk-4gocLaw/SvULSYd_lTI/AAAAAAAAOBg/Nbr9AkuCQaM/s72-c/CopyPasteSpider.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-5486587796800739789</id><published>2009-10-23T16:52:00.000-07:00</published><updated>2009-11-07T23:18:05.905-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='interviews'/><title type='text'>Interview questions revisited</title><content type='html'>Ive been experimenting with webmaster tools and analytics for this blog, and while running a Google search , I came across&lt;br /&gt;&lt;a href="http://www.experts-exchange.com/Software/Server_Software/Application_Servers/Java/BEA_WebLogic/Q_24000475.html+weblogic+portal+interview+questions"&gt;http://www.experts-exchange.com/Software/Server_Software/Application_Servers/Java/BEA_WebLogic/Q_24000475.html+weblogic+portal+interview+questions&lt;/a&gt; (Hint use Google Cache to see the answers )&lt;br /&gt;And on the BEA forums I see&lt;br /&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=919149&amp;amp;tstart=15"&gt;http://forums.oracle.com/forums/thread.jspa?threadID=919149&amp;amp;tstart=15&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ananthkannan.blogspot.com/2009/08/weblogic-portal-interview-questions_29.html"&gt;http://ananthkannan.blogspot.com/2009/08/weblogic-portal-interview-questions_29.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://venkataportal.blogspot.com/2009/09/comming-soon.html"&gt;http://venkataportal.blogspot.com/2009/09/comming-soon.html&lt;/a&gt;&lt;br /&gt;Compared with my own&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2007/02/weblogic-portal-interview-questions.html"&gt;http://theworkaholic.blogspot.com/2007/02/weblogic-portal-interview-questions.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://theworkaholic.blogspot.com/2009/10/weblogic-portal-interview-questions-ii.html"&gt;http://theworkaholic.blogspot.com/2009/10/weblogic-portal-interview-questions-ii.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There's a pretty big difference between the kind of questions I ask and the kind of questions people seem to think will be asked or indeed do ask. A multiple choice question? really? I guess that was picked up from the BEA certification exam. (The less said about certification the better).  Is there a point asking people something that's right there in the documentation or something that any respectable search engine could?&lt;br /&gt;Lets get some assumptions out of the way&lt;br /&gt;a. A bad resource is extremely detrimental to any software project. The contribution is negative and a big negative at that. It is better to not have the resource than have a bad resource.&lt;br /&gt;b. There isn't an easy way to eliminate a bad resource at a short listing phase.&lt;br /&gt;In most cases there are more people applying to the job than there are jobs. The resume is too abused to be an effective eliminator. If you look at a typical Java/EE resume , every specification in the EE umbrella is covered. Everyone has solid knowledge and expertise in all the specifications. On project experience is sometimes faked.&lt;br /&gt;Would a quick multiple choice easily corrected paper help? I believe that this is actually bad. The people who aren't that knowledgeable know it, and spend their time memorizing documents/api's etc before an interview and can probably game this test. The people who I know are good in their fields usually don't have much time or patience for the minutiae, but are quite capable of doing this on demand. Project Experience would be a good indicator, but it is costly to verify this before hand. References are usually given by friends and aren't reliable. Typically a interviewee isn't going to provide a reference to someone who will give him a negative review.&lt;br /&gt;&lt;br /&gt;So we can't rely on the short listing process to eliminate the bad apples. You must as an interviewer go to an interview thinking that you might be gamed.  This means that straightforward questions might be answered by a bad candidate. This doesn't mean that you should ask the brain teaser sort of questions which only indicate that the interviewee is good at solving brain teasers (or has Googled the answers).&lt;br /&gt;&lt;br /&gt;What then constitutes a good interview question?&lt;br /&gt;Here are my criteria&lt;br /&gt;a. The interviewee must be able to describe what he has worked on /is working on effectively. he must be confident in the modules he has worked. He must be able to answer questions related to his module when you vary some of the parameters. This is a deal breaker. A person who doesn't know what his project probably wont be able to handle yours either.&lt;br /&gt;b. Most of the technical questions I ask are conversational and to which there probably isn't a right answer. The question is just the opening gambit, E4 for chess players.  If I feel I am getting a recitation from documents , I introduce a twist or change a parameter of the problem (e.g. if the answer is something like I would design this with Spring by utilizing Dependency Injection IOC pattern and use the Hibernate ... - would be met with sorry the spring/hibernate license doesn't meet the project requirements, you can't use it).&lt;br /&gt;c. Hands on experience on the technologies Im looking for is always a great plus, but it isn't a dealbreaker for me. If you can handle JSP, you can handle JSF. If you can handle Struts, you can handle other controller frameworks. What I can't stand is when someone states about all the stuff he has worked on at the start, how he was the heart and soul of the entire project, the life of the party, later changes his tune to say well I didn't really work much on that particular part. Thats a deal breaker. Dishonesty means I can't trust any of the other wonderful things you said, bye bye.&lt;br /&gt;d. Never ask code questions without also providing the books, the documents, the search engine and a compiler. Writing code snippets on a whiteboard is stupid. Pseudo code questions are perfectly acceptable. Don't ask people to reinvent sorting algorithms when there are so many books (When will I ever buy that Donald Knuth book) that they could use. If you want to check analytical skills then use real life examples. There must have been numerous problems with your project, describe the circumstances and ask the resource to make suggestions.&lt;br /&gt;&lt;br /&gt;In some ways I'm glad that I don't have to conduct interviews anymore. The last time I was proudly telling my mother of how many people I have rejected, she said why am I depriving people from working , and that you don't know how much they might need the job. While I still stand by my assumption that no resource is better than a bad one, it's still disturbing to think that I might(probably) have made errors in judgement and maybe just maybe I rejected a deserving candidate and maybe just maybe he really needed it. Like I said I'm glad I don't make hire decisions anymore&lt;br /&gt;&lt;br /&gt;Throughout this post, I have referred to the interviewee as 'him'. Thats  probably due to that fact that more than 90% of the candidates I've interviewed are male. Which is a sad state of affairs for software.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-5486587796800739789?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/5486587796800739789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=5486587796800739789' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5486587796800739789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5486587796800739789'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/interview-questions-revisited.html' title='Interview questions revisited'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-3649090141278620623</id><published>2009-10-21T08:52:00.000-07:00</published><updated>2009-10-21T08:53:20.385-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Weblogic Portal'/><title type='text'>First Weblogic Portal Pro</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/St8uU2r_EVI/AAAAAAAAN58/BpcqFLCZ6yM/s1600-h/OTN+Discussion+Forums+-+WebLogic+Portal_1256140315993.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 289px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/St8uU2r_EVI/AAAAAAAAN58/BpcqFLCZ6yM/s320/OTN+Discussion+Forums+-+WebLogic+Portal_1256140315993.png" alt="" id="BLOGGER_PHOTO_ID_5395081814425407826" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I'd like to thank.....This shouldnt give me that much happiness, but it does.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-3649090141278620623?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/3649090141278620623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=3649090141278620623' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3649090141278620623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3649090141278620623'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/first-weblogic-portal-pro.html' title='First Weblogic Portal Pro'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_AOk-4gocLaw/St8uU2r_EVI/AAAAAAAAN58/BpcqFLCZ6yM/s72-c/OTN+Discussion+Forums+-+WebLogic+Portal_1256140315993.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1919243871865731944</id><published>2009-10-20T21:52:00.000-07:00</published><updated>2009-10-20T22:11:45.445-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='interviews'/><category scheme='http://www.blogger.com/atom/ns#' term='Weblogic Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><title type='text'>Weblogic Portal interview questions - II</title><content type='html'>The following are the Portal interview questions that ive used or kept or have been asked(in no particular order , and no answers either :) )&lt;br /&gt;I do not include questions (e.g. what is a nested pageflow) that can be answered with Google.&lt;br /&gt;Also see &lt;a href="http://theworkaholic.blogspot.com/2007/02/weblogic-portal-interview-questions.html"&gt;Weblogic Portal interview questions - I&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What options do you have for Single Sign On for a Weblogic Portal application (and in general). Give the advantages and disadvantages of each approach&lt;/li&gt;&lt;li&gt;If you are using WSRP, and the user is logged in to the consumer , is he also logged into the producer? If so how? If not how do you do this?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If you have standard static HTML application, how would you optimise this for performance? For each of the technique's you mention , how would this be implemented in Weblogic Portal&lt;/li&gt;&lt;li&gt;How do you ensure that a Weblogic Portal application is easily Searchable by external search engines like Google&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What are serious problems/ drawbacks of JSR 168/ JSR 286. Under what circumstances would you not use these for your portlet implementation?  Under what circumstances would you use these for your portlet implementation?&lt;/li&gt;&lt;li&gt;Why is asynchronous desktop a bad idea? In what situations does it become a good idea?&lt;/li&gt;&lt;li&gt;What circumstances can cause issues with Portal Propagation. Would you use propagation in your actual production? If not , why not?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;How would you integrate Flex / Any flash based widget into your portal application?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1919243871865731944?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1919243871865731944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1919243871865731944' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1919243871865731944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1919243871865731944'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/weblogic-portal-interview-questions-ii.html' title='Weblogic Portal interview questions - II'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-3651876066852335537</id><published>2009-10-12T18:34:00.000-07:00</published><updated>2009-10-12T18:50:43.606-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Detecting missing files with JMeter</title><content type='html'>I have lately found that JMeter is becoming my tool of choice for almost all the normal mundane programming tasks. Case in point.&lt;br /&gt;On my current website's we have a bunch of PDF's (150K) which are accessible only via search and have an entry in some table for that purpose. Each PDF is linked to a language and multiple countries so the total number of rows in the database are much more than the number of files. Now years later, due to human error and other causes some of these records exist in the database but there aren't corresponding PDF files on the webserver , which allows the user to see a link when he searches for the data but a 404 error when the user actually clicks it. I had to generate a report listing all these files.&lt;br /&gt;&lt;br /&gt;Constraints&lt;br /&gt;a. Administrators wont let you run a program on the web server.&lt;br /&gt;b. You could ask them to copy files to a separate directory but it takes about a week to get approval for anything related to production except for a Database copy (which is available immediately)&lt;br /&gt;&lt;br /&gt;I initially thought of asking for a recursive file name print of all the files from the webserver to compare against the database (but writing this Java program would have taken half a day to iron out the bugs) . So I settled on JMeter&lt;br /&gt;&lt;br /&gt;Run query to get a list of files and save it to a CSV (Squirrel SQL client) &lt;br /&gt;Thread Group (10 in parallel)&lt;br /&gt;  CSV Data Set&lt;br /&gt;  Http Request (HEAD) , the web link to the PDF is read from the CSV&lt;br /&gt;&lt;br /&gt;Run from command line with a sample_variables property set to fields from the CSV.&lt;br /&gt;Time to run test = 1.5 hrs. JMeter's sample HTML was good enough to be shown to the users to fix the issues.&lt;br /&gt;Whats great is that when the missing files are uploaded I can verify the data easily again.&lt;br /&gt;&lt;br /&gt;Now I could have used JMeter's JDBC sampler to eliminate the Squirrel client.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-3651876066852335537?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/3651876066852335537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=3651876066852335537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3651876066852335537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3651876066852335537'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/detecting-missing-files-with-jmeter.html' title='Detecting missing files with JMeter'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1949641365893844943</id><published>2009-10-06T15:08:00.000-07:00</published><updated>2009-10-08T21:44:06.862-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance Tuning'/><title type='text'>Profiling BEA Weblogic Portal Apps</title><content type='html'>Profiling a portal application running on earlier versions of BEA Weblogic  has always been somewhat painful(still is) if you aren't willing to pay for a commercial profiler(It still might be painful).  With Weblogic 8.1 I had used &lt;a href="http://eclipsecolorer.sourceforge.net/index_profiler.html"&gt;Eclipse Colorer&lt;/a&gt; but that doesn't seem to work with the later versions of Eclipse and hasn't been developed in a while, it crashed on Weblogic 10 (JDK 1.5). I tried out a few from the &lt;a href="http://java-source.net/open-source/profilers"&gt;Open Source Java Profilers&lt;/a&gt; page but some crashed the JVM and some didn't do what I want.&lt;br /&gt;The basic things were&lt;br /&gt;a. I needed to check execution times.&lt;br /&gt;b. I didn't want to recompile my application or make changes to code.&lt;br /&gt;&lt;br /&gt;I'd played around a bit with TPTP so I gave it a try and used it, it worked reasonably well, I eliminated some code that didn't cache data correctly , so all in all it was a success. I haven't had time to look through all the settings in detail , and I'm sure some of the settings are redundant , but they worked for me. I've created these steps using the latest available versions of TPTP/Eclipse.&lt;br /&gt;I ran the test in Windows Vista. Folks using a different O.S. are probably smart enough to not need these steps.&lt;br /&gt;&lt;br /&gt;Steps&lt;br /&gt;a. Install &lt;a href="http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/galileo/SR1/eclipse-jee-galileo-SR1-win32.zip"&gt;Eclipse IDE for Java EE Developers&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;b. Install the TPTP(4.6.1) plugin. There are a set of screens on how to do this - &lt;a href="http://wiki.eclipse.org/Install_TPTP_with_Update_Manager"&gt;http://wiki.eclipse.org/Install_TPTP_with_Update_Manager&lt;/a&gt;. You could also download the All in one which has Eclipse + TPTP. Also referred to a couple of links on TPTP. &lt;a href="http://www.eclipse.org/tptp/platform/documents/tutorials/jvmti/Java_Application_Profiling_using_TPTP-v2.0.html"&gt;Profiling J2SE 5.0 based applications&lt;/a&gt; and &lt;a href="http://www.eclipse.org/tptp/home/downloads/4.6.0/documents/installguide/InstallGuide46.html"&gt;TPTP installation guide&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;c.  Download the &lt;a href="http://www.eclipse.org/tptp/home/downloads/#agentController"&gt;agent controller for TPTP&lt;/a&gt;. Unzip it to a folder. Call this folder $AGENT_CONTROLLER_HOME&lt;br /&gt;&lt;br /&gt;d. Set a new environment variable&lt;br /&gt;JAVA_PROFILER_HOME=$AGENT_CONTROLLER_HOME\plugins\org.eclipse.tptp.javaprofiler&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5rfeioB6I/AAAAAAAANyM/8yLyFMlXYCs/s1600-h/sysvariables.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 174px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5rfeioB6I/AAAAAAAANyM/8yLyFMlXYCs/s320/sysvariables.jpg" alt="" id="BLOGGER_PHOTO_ID_5390363992527472546" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;e. Set up the PATH ( I did this in Control Panel --&gt; System --&gt; Advanced --&gt; Environment variables)&lt;br /&gt;$AGENT_CONTROLLER_HOME\plugins\org.eclipse.tptp.javaprofiler;$AGENT_CONTROLLER_HOME\bin;&lt;rest&gt;&lt;br /&gt;You should have Java in your path somewhere. I use the same JDK as that with BEA. (i.e. Java 1.5 . I did try Java 1.6, but it didn't work for me)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5ry8L1bAI/AAAAAAAANyU/8BbWgy3NkgQ/s1600-h/Path.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 235px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5ry8L1bAI/AAAAAAAANyU/8BbWgy3NkgQ/s320/Path.jpg" alt="" id="BLOGGER_PHOTO_ID_5390364326902459394" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I run on Windows Vista so all command prompts are launched with Run As Administrator including the BEA server.&lt;br /&gt;&lt;br /&gt;f. In a command window cd to $AGENT_CONTROLLER_HOME\bin and run setConfig. Specify the path to Java (1.5) and the other options, I chose the options in the screen below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5sqD4UqKI/AAAAAAAANyc/a9rDxUcw1PA/s1600-h/setconfig.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 44px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5sqD4UqKI/AAAAAAAANyc/a9rDxUcw1PA/s320/setconfig.jpg" alt="" id="BLOGGER_PHOTO_ID_5390365273860909218" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;g. Start the agent controller (ensure no firewall blocking or unblock) by running acserver.exe.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5s4Sv_cBI/AAAAAAAANyk/DsSNErNiUC4/s1600-h/acserver.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 156px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5s4Sv_cBI/AAAAAAAANyk/DsSNErNiUC4/s320/acserver.jpg" alt="" id="BLOGGER_PHOTO_ID_5390365518370664466" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;h. In a new command line window run SampleClient. If all is well, you should see the response. Close SampleClient command window but keep acserver running&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5tpi2uhpI/AAAAAAAANys/fU0YuZPPEOU/s1600-h/sampleclient.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 239px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5tpi2uhpI/AAAAAAAANys/fU0YuZPPEOU/s320/sampleclient.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390366364507473554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Setting up BEA&lt;/span&gt;&lt;br /&gt;i. Goto the BEA portal domain and change the following settings in setDomainEnv.cmd (these already exist , just change the values)&lt;br /&gt;set debugFlag=false&lt;br /&gt;set testConsoleFlag=false&lt;br /&gt;set iterativeDevFlag=false&lt;br /&gt;...&lt;br /&gt;set PRODUCTION_MODE=true&lt;br /&gt;&lt;br /&gt;Towards the bottom of the file (4-5 lines from the bottom), add the command to enable the profiler&lt;br /&gt;&lt;br /&gt;set JAVA_OPTIONS=%JAVA_OPTIONS%&lt;br /&gt;set JAVA_OPTIONS=-agentlib:JPIBootLoader=JPIAgent:server=controlled,filters=$DOMAIN_HOME\filters.txt;CGProf:execdetails=true %JAVA_OPTIONS%&lt;br /&gt;&lt;br /&gt;Here we specify that the process should wait (server=controlled) till we connect to it, specify some filters for packages that we have no interest in (and which would cause the system to be slower), specify that we want to capture executing details.&lt;br /&gt;&lt;br /&gt;Create a file named filters.txt in the path you have specified&lt;br /&gt;org.apache.* * EXCLUDE&lt;br /&gt;com.bea.* * EXCLUDE&lt;br /&gt;weblogic.* * EXCLUDE&lt;br /&gt;netscape.* * EXCLUDE&lt;br /&gt;antlr.* * EXCLUDE&lt;br /&gt;com.octetstring.* * EXCLUDE&lt;br /&gt;com.rsa.* * EXCLUDE&lt;br /&gt;org.omg.* * EXCLUDE&lt;br /&gt;javelin.* * EXCLUDE&lt;br /&gt;kodo.* * EXCLUDE&lt;br /&gt;org.opensaml.* * EXCLUDE&lt;br /&gt;com.pointbase.* * EXCLUDE&lt;br /&gt;serp.* * EXCLUDE&lt;br /&gt;com.solarmetric.* * EXCLUDE&lt;br /&gt;schemacom_bea_xml.* * EXCLUDE&lt;br /&gt;com.asn1c.* * EXCLUDE&lt;br /&gt;com.certicom.* * EXCLUDE&lt;br /&gt;&lt;br /&gt;When I hadn't filtered out kodo packages , I did get a ClassFormatError so at a minimum these packages must be filtered&lt;br /&gt;&lt;br /&gt;j. Now run startWeblogic. The process should wait(we specified server=controlled remember)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5t6HYFcAI/AAAAAAAANy0/rw2siQJ2Bks/s1600-h/weblogic-1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 159px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5t6HYFcAI/AAAAAAAANy0/rw2siQJ2Bks/s320/weblogic-1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390366649188970498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;k. Now start eclipse. Click Run --&gt; Profile Configurations. Click Attach to Agent and hit new icon. A new Configuration is created&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5uNqH1bCI/AAAAAAAANy8/y6Yh_yk0BV8/s1600-h/eclipse-1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 255px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5uNqH1bCI/AAAAAAAANy8/y6Yh_yk0BV8/s320/eclipse-1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390366984933567522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;l. Now click the agents tab, if all is well you should be able to see an entry&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5uf7E-2EI/AAAAAAAANzE/Q4fqPfTRtKY/s1600-h/eclipse-2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5uf7E-2EI/AAAAAAAANzE/Q4fqPfTRtKY/s320/eclipse-2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390367298722650178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;m. Double Click it and specify the filters (same as the ones specified in filters.txt)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5upiYRPpI/AAAAAAAANzM/3AZ3vBqISa0/s1600-h/eclipse-3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 246px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5upiYRPpI/AAAAAAAANzM/3AZ3vBqISa0/s320/eclipse-3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390367463891353234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;n. Click Next, Uncheck the run automatically, Click finish.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5uz8BeClI/AAAAAAAANzU/ym-G4Ys96vA/s1600-h/eclipse-4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 255px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5uz8BeClI/AAAAAAAANzU/ym-G4Ys96vA/s320/eclipse-4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390367642573736530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;o. Click Apply and Profile. Switch to the profile perspective. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5vB3Ryp4I/AAAAAAAANzc/iMunJclIJjE/s1600-h/eclipse-5.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 182px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5vB3Ryp4I/AAAAAAAANzc/iMunJclIJjE/s320/eclipse-5.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390367881818187650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We haven't started profiling yet, but the Weblogic server will now continue start up. You probably have to wait about 10 minutes.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5vMM3k47I/AAAAAAAANzk/949k2pV_8I0/s1600-h/eclipse-6.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 250px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Ss5vMM3k47I/AAAAAAAANzk/949k2pV_8I0/s320/eclipse-6.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390368059412505522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;p. Once Weblogic is in running mode , you can start the profiling by clicking the run icon in the left pane. You can also click the execution statistics (though this might be empty since we have filtered most of the default BEA code that runs.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5wj-1atqI/AAAAAAAANz8/vsBTL7j8Lgo/s1600-h/eclipse-7.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 175px;" src="http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5wj-1atqI/AAAAAAAANz8/vsBTL7j8Lgo/s320/eclipse-7.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390369567473841826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;q. Now exercise your application by accessing it in the browser or by running a test e.g. a JMeter test.&lt;br /&gt;You should now be able to see execution details in Eclipse. For e.g.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5wBgQp2lI/AAAAAAAANzs/0kyHMKzVJyo/s1600-h/eclipse-8.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 166px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5wBgQp2lI/AAAAAAAANzs/0kyHMKzVJyo/s320/eclipse-8.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390368975151028818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;which shows 100 calls being made to DBService. Double click it.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5wSI2fBmI/AAAAAAAANz0/b8e4rTEX2z0/s1600-h/eclipse-9.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 194px;" src="http://4.bp.blogspot.com/_AOk-4gocLaw/Ss5wSI2fBmI/AAAAAAAANz0/b8e4rTEX2z0/s320/eclipse-9.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390369260925027938" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;which shows the method calling it (TestService.getList() 1 call here makes a 100 calls to the DB , plus some BEA security checks). The TestService is called by the Portlet Controller as shown&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/Ss5xG-AblpI/AAAAAAAAN0E/3V6oCoG7rsM/s1600-h/eclipse-10.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 188px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/Ss5xG-AblpI/AAAAAAAAN0E/3V6oCoG7rsM/s320/eclipse-10.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5390370168547022482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And you can easily conclude that there is some sort of N+1 problem here. A single request leads to 100 db calls, after which inspect the code fix the problem, rerun the profile and verify that you only invoke the DB once.&lt;br /&gt;&lt;br /&gt;However there is a caveat here, it is far far easier to profile your code out of container. If you can separate out your code so that most of it runs outside Weblogic , then it's easier to profile it. And as we all know, this isn't always possible.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1949641365893844943?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1949641365893844943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1949641365893844943'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/10/profiling-bea-weblogic-portal-apps.html' title='Profiling BEA Weblogic Portal Apps'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_AOk-4gocLaw/Ss5rfeioB6I/AAAAAAAANyM/8yLyFMlXYCs/s72-c/sysvariables.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-6948761155233629752</id><published>2009-09-10T15:42:00.000-07:00</published><updated>2009-09-10T16:49:08.243-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Running JMeter  for a large number of concurrent threads</title><content type='html'>A common repeated question (Observation JMeter users probably don't use Google) on the JMeter forums goes something like&lt;br /&gt;&lt;span style="font-style: italic;"&gt;I need to run N000 users concurrently and I have a Windows/Unix/Mac with N GB RAM , will that work? or how do I run N000 users from JMeter or Im running N000 users concurrently against my server, am I performance testing this correctly?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And the correct answer is (like all things related to performance testing) , test it out and see for yourself. This doesn't mean that there aren't rule of thumb's that you can follow but that no one can give you a definitive answer.&lt;br /&gt;&lt;br /&gt;My rules of thumb&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Know the load your client machines can generate approximately&lt;/span&gt;(for your test) - On my Windows PC (with Vista and 3GB RAM, running JMeter with a heap of 1 GB, dual core 2.4GHZ) if I run more than 100 threads, my machine starts to hang. I can't use any other applications so I normally wouldn't run a single JMeter instance with &gt; 100 threads for a machine configured like mine (But my tests usually don't have think times and delays). But this is a rule of thumb not a commandment. if I run Reliability and Performance monitor and check out the health of my PC , and I find it reasonably healthy then I can increase the threads, if not I'll reduce them. I also verify visually that the response time that JMeter seems to be giving me (by directly checking the JTL or CSV file being generated)  is approximately the same as if I accessed the page(just the html using a proxy or browser sniffer) from a browser running on a &lt;span style="font-weight: bold; font-style: italic;"&gt;different machine&lt;/span&gt;. We did have a case where a tester used LoadRunner to generate loads for 2000 users from a single machine which started giving him average response times of &gt; 2 minutes but people who accessed the site saw response time of 15-20 seconds. The machine which was generating the load couldn't handle these many threads/sockets and was the bottleneck rather than the application being tested. This is also dependent on your test scripts and your application under test. Test scripts that have delays between requests will obviously be able to handle larger number of  threads (because there wont be as many concurrent threads).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Run separate instances of JMeter (instead of master-slave)&lt;/span&gt; - Jmeter allows you to run a test in master slave mode (With 1..n slaves). The advantage of this that you get all the results at the master as well as the start times etc can be more or less synchronized. However the overhead has now increased , as well as the problem that supposedly this bit of JMeter is not designed too well. Its better to run separate instances of JMeter and combine the results (if CSV is chosen as the output file format, then this is as simple as file concatenation, if XML you need to do a little more work, but its easy as well). You could split up the test itself (e.g. 100 users browsing 100 users logging in could be split up into two jmeter tests) or run the same test with some threads per machine.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Run in command line mode, Disable all Listeners and preferably use CSV as your output format. Understand JVM options. &lt;/span&gt;JMeter is a java application , if you want the most out of your JMeter client you should run it light and you should know how to tune a java application (the Java Heap especially).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Understand your actual requirements&lt;/span&gt;. Far too often testers don't know the difference between logged in users and concurrent users. Or think times. Or how http works. Or how their app works. Or why input data to the test should be varied (our App cached data and try as we might we couldn't get the tester to understand that if all the concurrent users browsed the exact same page, everyone except the first user's will get really fast times). Second normal users take a lot of time to read a page, fill in form fields, pause between requests, drink a cup of coffee whatever, The number of user's with an active session is always greater than the number of user's actually doing something at the same time (and in a lot of cases far greater). Check your site with realistic (plus safety margin )numbers. If there are 100 concurrent users at peak times in your system then check with numbers close to it first before you want to test out 10,000 concurrent users&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Performance testing goes hand in hand with tuning&lt;/span&gt;. Sometimes questions are asked of the sort 'I increased the load , &lt;span style="font-style: italic;"&gt;I get SocketExceptions or the Applications responds very slowly , help&lt;/span&gt;!'. Well this is what you expect your test to tell you right? You now need to check why your application is responding slowly , using logs, profilers whatever. Rule of thumb tune , test, tune, test, tune, test, tune as often as you can.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-6948761155233629752?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/6948761155233629752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=6948761155233629752' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/6948761155233629752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/6948761155233629752'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/09/running-jmeter-for-large-number-of.html' title='Running JMeter  for a large number of concurrent threads'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-5356450462177509203</id><published>2009-08-23T22:07:00.000-07:00</published><updated>2009-08-23T22:25:38.627-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance Tuning'/><title type='text'>Performance Tuning tales</title><content type='html'>When you ask a J2EE guy something about performance tuning you'd probably get something that includes JVM tuning heap space, survivor ratio's , types of GC or you might get the don't use EJB , minimise the number of remote calls , or the use Hibernate , use Prepared Statements, use Cache etc etc.  Interestingly enough for my current project we had implemented most of the above, tested it locally and seemed to get &lt;4 second times for most pages. And we missed a big problem (hint it's a web based system) , can you guess?&lt;br /&gt;The system responds in under 4 seconds when accessed locally. When accessed through a browser based in New York some (Can you guess?) requests take 20+ seconds. Luckily we did run external tests as soon as the production systems were available so we found this out a couple of months before the system was actually released. &lt;br /&gt;In any case , in hindsight as soon as we knew the problem existed it was relatively easy to guess and verify(YSlow) the problems. We only had few small images so we knew the problem wasn't there.&lt;br /&gt;a. Whats good for development isn't necessarily good for deployment. e.g. We do normally split CSS files , Javascript files and include them separately. Yes a browser will cache these files ( you do add Etags don't you?), but the first request and HTTPS will be slow if the browser must make these connections (normally at the most two at a time). - We used Yahoo and ANT  to combine the CSS into one file and the Javascript  into another (at build time) drastically reducing the response times&lt;br /&gt;b. GZIP. Creating Gzipped versions of the files and dynamically gzipping all the content (a flag on the webserver) also brought down the times.&lt;br /&gt;Just doing the above brought down the times to under 4 seconds even when the site was accessed remotely on limited bandwidth clients.&lt;br /&gt;Moral of the story : Always test , never guess when it comes to performance tuning.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-5356450462177509203?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/5356450462177509203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=5356450462177509203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5356450462177509203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5356450462177509203'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/08/performance-tuning-tales.html' title='Performance Tuning tales'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1005649157957277885</id><published>2009-08-19T22:08:00.000-07:00</published><updated>2009-08-19T22:41:00.454-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Testing</title><content type='html'>There are various kinds of test's that can be performed on a system , but it looks like most engineers don't agree on the definition of the test. For e.g. in my current project a 'unit test' tests out the end to end functionality but it must be performed by a developer i.e. any test that a developer performs is a unit test!&lt;br /&gt;In any case this is my usage&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Unit Test&lt;/span&gt; - Generally meant to represent that only a small subset of the code is under test. You might find a few fanatics who argue to the effect that anything that goes to the database isn't a unit test, anything that needs an external interface isn't a unit test etc etc.  Ignore them. The key is that the test might not exercise the flow as it finally would. There might be mocked interfaces, hardcoded data. Generally written by developers and generally easier to automate. Unit tests are also low hanging fruit, and contrary to what most agile engineers will tell you, are pretty much useless expect to impress some manager with 'We have automated unit tests!' , 'We have continuous builds with JUnit reports!','We have 99% code coverage!'. The quality of these tests written is mostly poor (they are written by developers after all), the test data provided rarely covers boundary conditions, invalid data, exceptional conditions. Yes Yes I know you should have high code coverage. It's quite easy to game the high code coverage (which is what happens when metrics are imposed by management) but even if it wasn't, the code coverage is only as good as the code and the test.&lt;br /&gt;e.g. function int add(int one, int two) {&lt;br /&gt;  return 4;&lt;br /&gt;}&lt;br /&gt;Test function with add(2,2), add(-1,5) , 100% code coverage , automated unit tests all green , mission accomplished!?&lt;br /&gt;i.e. If the developer doesn't account for the boundary conditions in code, he isn't likely to test out those scenarios either.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Integration Test&lt;/span&gt; - Generally tests out the interface between multiple systems, though the data might be faked. If there are only two types of test that you can carry out on your system then this is one of them.&lt;br /&gt;These tests are extremely hard to write (or atleast make it repeatable), and are very very useful. The earlier you can have these tests up and running on your system, the better the quality of your system.  These tests are hard to write not because of technical problems(which exist) but because of people issues. Different systems are normally run by different teams (sometimes even external to your organisation) have their own schedules , develop at their own pace and make their own assumptions and are notoriously non co-operative.  Technical limitations are normally due to non repeatable time sensitive data which either needs the data reset to a known state or data created from scratch. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Functional Test (End to End test&lt;/span&gt;). - Tests out functionality from a user's perspective.  This is the second type of test that must be run and the earlier you can run these tests in your system the better the quality of the system is. Normally nothing is faked , actual data is used for the tests. When these tests are performed by a business user / stake holder these become Acceptance tests. These tests are extremely important and difficult to fully automate. e.g. These would also include UI tests (this page doesnt work on &lt;span style="font-weight: bold; font-style: italic;"&gt;my &lt;/span&gt;browser!). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Performance/Load&lt;/span&gt; - Functional tests run in parallel (normally a good mixture) with varying concurrent users. Easy to do if the functional tests can be automated. In most cases difficult to simulate (especially if the system is already live, easier to do the first time). Depending on the duration you run this is also by different names. Some organizations refer to long running tests as smoke tests. (used to smoke out memory leaks) whereas some organisations use smoke tests to refer to some important functional tests that are run to check that no major errors exist.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;System Test&lt;/span&gt;s - Used to check that all systems are up and running. Not really a test category by itself , but useful to abort test runs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1005649157957277885?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1005649157957277885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1005649157957277885' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1005649157957277885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1005649157957277885'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/08/testing.html' title='Testing'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-6675423995705152702</id><published>2009-06-25T15:10:00.000-07:00</published><updated>2009-06-25T15:11:18.003-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google Juice'/><title type='text'>Google this!</title><content type='html'>&lt;a href="http://www.bio-rad.com/evportal/evolutionPortal.portal?_nfpb=true&amp;amp;_pageLabel=verticalLandingPage&amp;amp;catID=1100&amp;amp;country=US&amp;amp;lang=en&amp;amp;javascriptDisabled=true"&gt;Life Science Research&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.bio-rad.com/evportal/evolutionPortal.portal?_nfpb=true&amp;amp;_pageLabel=verticalLandingPage&amp;amp;catID=1200&amp;amp;country=US&amp;amp;lang=en&amp;amp;javascriptDisabled=true"&gt;Clinical Diagnostics&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.bio-rad.com/evportal/evolutionPortal.portal?_nfpb=true&amp;amp;_pageLabel=verticalLandingPage&amp;amp;catID=1300&amp;amp;country=US&amp;amp;lang=en&amp;amp;javascriptDisabled=true"&gt;Spectroscopy&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.bio-rad.com/evportal/evolutionPortal.portal?_nfpb=true&amp;amp;_pageLabel=verticalLandingPage&amp;amp;catID=1400&amp;amp;country=US&amp;amp;lang=en&amp;amp;javascriptDisabled=true"&gt;Process Separations&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.bio-rad.com/evportal/evolutionPortal.portal?_nfpb=true&amp;amp;_pageLabel=verticalLandingPage&amp;amp;catID=1475&amp;amp;country=US&amp;amp;lang=en&amp;amp;javascriptDisabled=true"&gt;Food/Animal/Environment Testing&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.bio-rad.com/evportal/evolutionPortal.portal?_nfpb=true&amp;amp;_pageLabel=verticalLandingPage&amp;amp;catID=1450&amp;amp;country=US&amp;amp;lang=en&amp;amp;javascriptDisabled=true"&gt;Life Science Education&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-6675423995705152702?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/6675423995705152702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=6675423995705152702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/6675423995705152702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/6675423995705152702'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/google-this.html' title='Google this!'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4670964494942902605</id><published>2009-06-10T20:45:00.000-07:00</published><updated>2009-10-24T13:29:01.222-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Fixing URLs</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Motivation&lt;/span&gt;&lt;br /&gt;For some tests, the URL to visit is extracted from the previous request using one of the PostProcessors (usually the Regex PostProcessor). However a URL containing parameters should normally have ampersands(&amp;amp;) escaped . This causes problems because JMeter will not automatically unescape these URL's&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;&lt;br /&gt;Use a javascript function to unescape the urls.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sample&lt;/span&gt;&lt;br /&gt;Assume that the Regex Post processor has extracted the url into a variable named returnUrl, then in the next HTTPSampler (Path field), instead of using ${returnUrl} use the function below.&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;${__javaScript('${returnUrl}'.replace(/amp;/gi\,''))}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will simply replace amp; with a blank string so that a URL of the form http://www.yoursite.com/page?param1=value1&amp;amp;param2=value2 becomes&lt;br /&gt;http://www.yoursite.com/page?param1=value1&amp;amp;param2=value2&lt;br /&gt;&lt;br /&gt;Note that we don't need to do this for &lt;span style="font-weight: bold; font-style: italic;"&gt;encoded&lt;/span&gt; values like %2F or whatever because that is taken care by the webserver&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4670964494942902605?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4670964494942902605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4670964494942902605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4670964494942902605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4670964494942902605'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/fixing-urls.html' title='Fixing URLs'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-8240222348815270636</id><published>2009-06-10T10:22:00.000-07:00</published><updated>2009-06-10T10:24:27.255-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><title type='text'>First Weblogic Portal Journeyman - WooHoo</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/Si_sOUdKu2I/AAAAAAAAIpA/qLTaySvAGwI/s1600-h/OTN+Discussion+Forums+-+WebLogic+Portal_1244654554333.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 257px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/Si_sOUdKu2I/AAAAAAAAIpA/qLTaySvAGwI/s320/OTN+Discussion+Forums+-+WebLogic+Portal_1244654554333.png" alt="" id="BLOGGER_PHOTO_ID_5345751013465439074" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-8240222348815270636?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/8240222348815270636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=8240222348815270636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8240222348815270636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8240222348815270636'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/first-weblogic-portal-journeyman-woohoo.html' title='First Weblogic Portal Journeyman - WooHoo'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/Si_sOUdKu2I/AAAAAAAAIpA/qLTaySvAGwI/s72-c/OTN+Discussion+Forums+-+WebLogic+Portal_1244654554333.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4253995437019502248</id><published>2009-06-09T20:26:00.000-07:00</published><updated>2009-06-10T20:43:20.040-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Data DrivenTesting(from a database)</title><content type='html'>Motivation&lt;br /&gt;Data to a test needs to be varied , however the input needs to be constrained to a set of values(normally in some database table). E.g. check the prices of the top 10 items. Here we need to provide 10 item ids , however if these values are kept in a CSV file , then the file needs to be repeatedly updated. There needs to be a way to get these values to the test at runtime&lt;br /&gt;&lt;br /&gt;Solution&lt;br /&gt;Use the JDBC Request Sampler to fetch the data at runtime. Use either the Save Responses to a file or a BeanShell post processor to write the data to a file. Finally use the CSV Data Set Config to read this data.&lt;br /&gt;&lt;br /&gt;Sample&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4253995437019502248?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4253995437019502248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4253995437019502248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4253995437019502248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4253995437019502248'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/data-driventestingfrom-database.html' title='Data DrivenTesting(from a database)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4463166372972635958</id><published>2009-06-07T14:54:00.000-07:00</published><updated>2009-06-09T20:38:25.042-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Varying the data to the test</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Motivation&lt;/span&gt;&lt;br /&gt;The same test's need to be run, but the data we pass to it must be varied.&lt;br /&gt;In addition further tests may need to change their behavior depending on the data. E.g. A user registering may provide different data , and subsequent screens may change depending on what the user has entered or may be skipped altogether. A common scenario is when a user registers to a site has various options he can choose from , and we need to test the behavior of the site for different combinations&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;&lt;br /&gt;JMeter provides multiple ways to vary the data&lt;br /&gt;a. Use of User Parameters [1]&lt;br /&gt;b. Use of Variables [2]&lt;br /&gt;c. CSV Data Set Config [3]&lt;br /&gt;The solution we will use is Option c.&lt;br /&gt;&lt;br /&gt;The advantage of using CSV Data Set Config is that the data is externalised from the test , and can be updated by any user including a non technical business person. By making the assertion a part of the data, users can add more tests without needing the test itself to be modified. The other advantage of a CSV Data Set Config over a User Parameters pre processor is that the number of items that will be tested is fixed independent of the number of threads you will run (assuming you write the test in that fashion) OR can be made dependent on the number of threads. User Parameters is more closely tied to the number of threads.&lt;br /&gt;e.g. If you wanted to create 10 distinct users , you'd only have 10 rows in your CSV data set config and you could use 1 to 10 threads. But if you needed to do this with User Parameters you'd probably need to specify exactly 10 threads.&lt;br /&gt;&lt;br /&gt;So the solution takes the form of&lt;br /&gt;a. Create a CSV Data Set Config element and point it to the CSV files.&lt;br /&gt;b. Create your tests to use this data&lt;br /&gt;If you want as many tests as you have rows in your CSV file, then you can either end the thread or use a Loop Controller an check for the special value '&lt;eof&gt;'&amp;lt;EOF&amp;gt;"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sample &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References&lt;/span&gt;&lt;br /&gt;[1] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTTP_User_Parameter_Modifier"&gt;User Parameters&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#User_Defined_Variables"&gt;Variables&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#CSV_Data_Set_Config"&gt;CSV Data Set Config&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/eof&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4463166372972635958?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4463166372972635958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4463166372972635958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4463166372972635958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4463166372972635958'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/varying-data-to-test.html' title='Varying the data to the test'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-906479531085364377</id><published>2009-06-05T19:21:00.000-07:00</published><updated>2009-06-05T23:00:45.339-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Testing multiple environments with JMeter</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Motivation&lt;/span&gt;&lt;br /&gt;Most projects have a number of environments through which the code moves. e.g. A Development environment, A Test environment, A User Acceptance test environment, A reference environment and finally the Production environment. Hence the same test script is to be targeted to multiple environments. In theory all of this is automated , and anything that succeeds/fails in one environment would succeed/fail consistently in all other environments. However environmental differences and human errors almost always cause one to hear &lt;span style="font-style: italic;"&gt;"But it works on my machine"&lt;/span&gt;&lt;br /&gt;Whats needed is a way to run the same test against different environments easily&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;&lt;br /&gt;An assumption we are going to make here is that these tests are automated and would be run from the command line, in our case using ANT.&lt;br /&gt;The solution has to address two basic requirements&lt;br /&gt;a. Parameterization of the various environments&lt;br /&gt;b. You should still be able to run the test in GUI mode (when you are modifying/extending the test)&lt;br /&gt;To implement this we will use JMeter properties[1] and use normal ANT [2],[3] features.&lt;br /&gt;&lt;br /&gt;While writing the HTTP tests, add an HTTP Request Default element&lt;br /&gt;&lt;br /&gt;If the Server name or IP is to be varied then enter&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;${__property(run.server,,yourdevserver.com)}&lt;/span&gt;&lt;br /&gt;This will look for a property named run.server , but will use &lt;span style="font-style: italic;"&gt;yourdevserver.com&lt;/span&gt;  if no property is specified. For the third parameter, use the server against which you want to run the test while running in GUI mode.&lt;br /&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0in;"&gt; Finally in your Build Script that you use to run Jmeter&lt;/p&gt;      &lt;p style="margin-bottom: 0in;"&gt; &amp;lt;jmeter jmeterhome=".." testplan="${run.test.plan}"&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;  resultlog="${report.dir}/${run.test.report}-${run.env}-${DSTAMP}${TSTAMP}.jtl"&amp;gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;    &amp;lt;property name="jmeter.save.saveservice.output_format" value="xml"/&amp;gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;        &amp;lt;&lt;b&gt;property name="run.server" value="${run.server}" /&lt;/b&gt;&amp;gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt; &amp;lt;/jmeter&amp;gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;    &lt;property name="jmeter.save.saveservice.output_format" value="xml"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/property&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;&lt;b&gt;    &lt;property name="run.server" value="${run.server}"&gt;&lt;/property&gt;&lt;/b&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;where the ANT property run.server can be varied to run this against different environment.&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-weight: bold;"&gt;Sample&lt;/span&gt; &lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;TODO attach ant and jmx file.&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;span style="font-weight: bold;"&gt;References&lt;/span&gt;&lt;br /&gt;[1] &lt;a href="http://jakarta.apache.org/jmeter/usermanual/functions.html#__property"&gt;JMeter Properties&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://www.programmerplanet.org/pages/projects/jmeter-ant-task.php"&gt;JMeter Ant task&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://ant.apache.org/manual/index.html"&gt;Ant Manual&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-906479531085364377?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/906479531085364377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=906479531085364377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/906479531085364377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/906479531085364377'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/testing-multiple-environments-with.html' title='Testing multiple environments with JMeter'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1015741590548233819</id><published>2009-06-05T18:57:00.000-07:00</published><updated>2009-06-05T19:17:19.175-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='JMeter'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>JMeter Prologue</title><content type='html'>I've been testing my existing work application using JMeter for the last 6 months , so what follows are a series of posts that I think isn't covered in most documentation or available online easily or in the same place (I had to figure out these solutions myself). However there is a caveat to that, the solution may not be the best possible one , may not be efficient and there may be more elegant ways to do what the solution does. In which case please inform me. However the solutions do have one thing in common, they worked for me. Your mileage may vary.&lt;br /&gt;&lt;br /&gt;The rest of the post is a rant , feel free to move on&lt;br /&gt;A few observations on a Friday(with a tip of the hat to BusyBee)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That people who keep asking for Unit Tests don't have a clue about testing web based applications.&lt;br /&gt;&lt;br /&gt;That data driven integration testing between multiple systems is damn hard to do , but boy is it satisfying when you actually find a defect due to it, and boy is it worth your time to develop these tests.&lt;br /&gt;&lt;br /&gt;That open source tools are so much better than some of the paid commercial tools. Except when it comes to presentation of the reports. Which surprisingly is also the difference between a Techie and a Manager.&lt;br /&gt;&lt;br /&gt;That there still is no tool to truly perform visual tests on a website. &lt;br /&gt;And That someone who could develop such a tool could make a lot of money.&lt;br /&gt;And that someone wont be me.&lt;br /&gt;&lt;br /&gt;That there is no time to test all the normal cases, much less the weird corner ones. and that there would always have been plenty of time in hindsight, if we had just gotten our act together earlier&lt;br /&gt;&lt;br /&gt;That a successful test is the one that fails in local,development, test, QA , UAT environments. That a test thats succeeds in the above environments but fails on the production environment is a pain.&lt;br /&gt;&lt;br /&gt;That a web based test should never underestimate the ignorance of a user.&lt;br /&gt;&lt;br /&gt;That developers do not make good testers. And that most developers are better testers than the official testing team, especially when we test other developers code. And that scares me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1015741590548233819?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1015741590548233819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1015741590548233819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1015741590548233819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1015741590548233819'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/06/jmeter-prologue.html' title='JMeter Prologue'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1910712569376338325</id><published>2009-04-30T13:35:00.000-07:00</published><updated>2009-05-06T22:11:28.035-07:00</updated><title type='text'>Almost there</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_AOk-4gocLaw/SgJteEygOqI/AAAAAAAAIMQ/FIEQycAj2lQ/s1600-h/OTN+Discussion+Forums+-+WebLogic+Portal_1241673007303.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://1.bp.blogspot.com/_AOk-4gocLaw/SgJteEygOqI/AAAAAAAAIMQ/FIEQycAj2lQ/s320/OTN+Discussion+Forums+-+WebLogic+Portal_1241673007303.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5332945272209160866" /&gt;&lt;/a&gt;&lt;br /&gt;Updated&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AOk-4gocLaw/SfoMQSXtfuI/AAAAAAAAICA/r6DzUqWRPHs/s1600-h/OTN+Discussion+Forums+-+WebLogic+Portal_1241123424115.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 323px;" src="http://3.bp.blogspot.com/_AOk-4gocLaw/SfoMQSXtfuI/AAAAAAAAICA/r6DzUqWRPHs/s400/OTN+Discussion+Forums+-+WebLogic+Portal_1241123424115.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5330586582895132386" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1910712569376338325?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1910712569376338325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1910712569376338325' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1910712569376338325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1910712569376338325'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2009/04/almost-there.html' title='Almost there'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AOk-4gocLaw/SgJteEygOqI/AAAAAAAAIMQ/FIEQycAj2lQ/s72-c/OTN+Discussion+Forums+-+WebLogic+Portal_1241673007303.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1920097795254456585</id><published>2008-02-02T18:25:00.000-08:00</published><updated>2008-02-02T18:29:53.335-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='Creational'/><title type='text'>Prototype</title><content type='html'>&lt;a href="http://bp3.blogger.com/_AOk-4gocLaw/R6Umx8WxSFI/AAAAAAAAASY/nuh2FNQDITU/s1600-h/Prototype.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5162575187307219026" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://bp3.blogger.com/_AOk-4gocLaw/R6Umx8WxSFI/AAAAAAAAASY/nuh2FNQDITU/s320/Prototype.jpg" border="0" /&gt;&lt;/a&gt;&lt;strong&gt;Name&lt;/strong&gt; : Prototype&lt;br /&gt;&lt;div&gt;&lt;strong&gt;Context&lt;/strong&gt; : Obtain a copy&lt;/div&gt;&lt;div&gt;&lt;strong&gt;Consequences&lt;/strong&gt; :&lt;/div&gt;&lt;div&gt;1)Add remove products at runtime&lt;br /&gt;2)Specify new objects by varying value or structure&lt;br /&gt;3)Reduced Subclassing &lt;/div&gt;&lt;div&gt;4)Configure an application with class dynamically&lt;/div&gt;&lt;div&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;Anything implementing clone(), &lt;/div&gt;&lt;div&gt;Class&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1920097795254456585?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1920097795254456585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1920097795254456585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1920097795254456585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1920097795254456585'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/02/prototype.html' title='Prototype'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_AOk-4gocLaw/R6Umx8WxSFI/AAAAAAAAASY/nuh2FNQDITU/s72-c/Prototype.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-4823905384737138989</id><published>2008-02-02T18:21:00.000-08:00</published><updated>2008-02-02T18:29:27.069-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='Creational'/><title type='text'>Factory method</title><content type='html'>&lt;a href="http://bp3.blogger.com/_AOk-4gocLaw/R6UmD8WxSEI/AAAAAAAAASQ/8aS0AbK3lAo/s1600-h/FactoryMethod.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5162574397033236546" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://bp3.blogger.com/_AOk-4gocLaw/R6UmD8WxSEI/AAAAAAAAASQ/8aS0AbK3lAo/s320/FactoryMethod.jpg" border="0" /&gt;&lt;/a&gt;&lt;strong&gt;Name&lt;/strong&gt; : Factory Method&lt;br /&gt;&lt;strong&gt;Context&lt;/strong&gt; : Hide the implementation class but defer the instantiation to subclass&lt;br /&gt;&lt;div&gt;&lt;strong&gt;Consequence&lt;/strong&gt;&lt;br /&gt;a) Provides hooks for subclass&lt;/div&gt;&lt;div&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;Calendar.getInstance()&lt;/div&gt;&lt;div&gt;Connection conn = java.sql.DriverManager.getConnection(uri, name, password);&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-4823905384737138989?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/4823905384737138989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=4823905384737138989' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4823905384737138989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/4823905384737138989'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/02/factory-method.html' title='Factory method'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_AOk-4gocLaw/R6UmD8WxSEI/AAAAAAAAASQ/8aS0AbK3lAo/s72-c/FactoryMethod.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-8926354268836638399</id><published>2008-02-01T18:02:00.000-08:00</published><updated>2008-02-02T18:21:44.537-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='Creational'/><title type='text'>Abstract Factory</title><content type='html'>&lt;a href="http://bp2.blogger.com/_AOk-4gocLaw/R6PP5MWxSDI/AAAAAAAAASE/vvlG7zW88-A/s1600-h/AbstractFactory.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5162198179372943410" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://bp2.blogger.com/_AOk-4gocLaw/R6PP5MWxSDI/AAAAAAAAASE/vvlG7zW88-A/s320/AbstractFactory.jpg" border="0" /&gt;&lt;/a&gt;&lt;strong&gt;Name&lt;/strong&gt; : Abstract Factory&lt;br /&gt;&lt;strong&gt;Context&lt;/strong&gt; : Creating Related family of objects&lt;br /&gt;&lt;strong&gt;Example&lt;/strong&gt;: Toolkit(awt) &lt;div&gt;java.sql.Connection (sort of creates Statements and PreparedStatements and CallableStatements where each is specific to the database)&lt;br /&gt;&lt;strong&gt;Consequence&lt;/strong&gt;&lt;br /&gt;1) Exchange Product Families&lt;br /&gt;2) Supporting new kinds of products&lt;br /&gt;3) Factories are normally singletons! But they need not be.&lt;/div&gt;&lt;div&gt;4)Note that every factory must support every type of object to be created. This is sometimes problematic.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-8926354268836638399?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/8926354268836638399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=8926354268836638399' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8926354268836638399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/8926354268836638399'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/02/abstract-factory.html' title='Abstract Factory'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_AOk-4gocLaw/R6PP5MWxSDI/AAAAAAAAASE/vvlG7zW88-A/s72-c/AbstractFactory.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-745495611423304811</id><published>2008-02-01T17:03:00.000-08:00</published><updated>2008-02-01T17:56:36.705-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='Creational'/><title type='text'>Singleton (Creational)</title><content type='html'>&lt;a href="http://bp2.blogger.com/_AOk-4gocLaw/R6PNnMWxSCI/AAAAAAAAAR8/X_zpYQaDw34/s1600-h/singleton.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5162195671112042530" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://bp2.blogger.com/_AOk-4gocLaw/R6PNnMWxSCI/AAAAAAAAAR8/X_zpYQaDw34/s320/singleton.jpg" border="0" /&gt;&lt;/a&gt; &lt;strong&gt;Name&lt;/strong&gt; : Singleton&lt;br /&gt;&lt;strong&gt;Comment&lt;/strong&gt; : Probably the best known (atleast if you go by answers you get in interviews to the question 'Patterns you have used') of the design patterns and probably one of the text book cases of people ignoring understand the context and understand the consequences when it comes to this pattern&lt;br /&gt;&lt;strong&gt;Context&lt;/strong&gt; : Need only 1(or a fixed or controllable number of instances) (e.g. memory consumption , or heavy initialization like reading a file,a requirement - there is only one Neo, a pre java 1.5 enum such that == can be used )&lt;br /&gt;&lt;strong&gt;Examples&lt;/strong&gt; : Single Instance (java.awt.Toolkit, Inspector)&lt;br /&gt;&lt;strong&gt;Consequences : &lt;/strong&gt;&lt;br /&gt;a) Controlled access to state&lt;br /&gt;b) Permits a variable number of instances (e.g. access to any object pool)!&lt;br /&gt;c) Watch out for real world multiple managed servers, clusters etc(older versions of Expresso framework used an in memory primary key generator as an incremented singleton - no use in a cluster. Real world naive code that uses a timestamp plus ip address as unique key through a singleton)&lt;br /&gt;d) Watch out for synchronized access for loading the singleton, thread safety, shared state.&lt;br /&gt;e) Watch out for serializable (might break singletoness if you dont follow effective java)&lt;br /&gt;f) Watch out for static block errors during initialization(if initialising eagerly). Will cause NoClassDefFoundErrors.&lt;br /&gt;g) Watch out for being unable to reset a singleton (e.g. a singleton that reads a file and stores it.If your not careful , changing the file needs a bounce of the server)&lt;br /&gt;h) Watch out for singletonitis. i.e. Making classes singleton even when there is no shared state, no performance or initialisation penalty.&lt;br /&gt;i) Watch out for problems testing the singleton&lt;br /&gt;&lt;br /&gt;With all the Watch out's is this pattern worth the trouble? read the context!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-745495611423304811?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/745495611423304811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=745495611423304811' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/745495611423304811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/745495611423304811'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/02/singleton-creational.html' title='Singleton (Creational)'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_AOk-4gocLaw/R6PNnMWxSCI/AAAAAAAAAR8/X_zpYQaDw34/s72-c/singleton.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-3111134611286609745</id><published>2008-02-01T16:22:00.000-08:00</published><updated>2008-02-01T16:49:20.749-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Design Patterns Course</title><content type='html'>The following series of posts deal with a design pattern course I conducted for a few colleagues of my team who insisted that I knew enough to conduct such a course(I don't). One of the problems I had faced while attending the design patterns course conducted by probably the best Technical Manager I've worked under (Homi Bharda) was that practical examples were hard to come by, where you could see the usefullness and though the Design patterns book by Erich Gamma did point to some examples they almost always dealt with GUI heavy , stateful , highly object oriented programs while at that stage I dealt with mostly stateless CRUD web based applications.&lt;br /&gt;I resolved that any course I took would show practical examples and what better example than the Java API which was quite familiar to my colleagues. I also had a lot of problem differentiating between patterns. Some of the Factory patterns looked alike. Some of the patterns like Command and Strategy looked alike. I resolved to have some comparisons at least.&lt;br /&gt;&lt;br /&gt;What these notes dont have is my bitterly cynical comments e.g. of people who code such that all their classes have a suffix which is pattern e.g. ObjectCommand uses an ObjectFacade uses an ObjectFactory creates an ObjectService which uses an ObjectDAO and returns an ObjectAdapter which wraps an ObjectDecorator which wraps a ObjectDTO (Disclaimer I have done this too). This literally is the developer's cry look Im a designer , I use patterns , I even know their names! But ask them Give me some examples of design patterns in the Java SDK and we have a) Blank Stares b) Singleton c) A very very few Decorator.&lt;br /&gt;So anyway other than the above rant , very few cynical comments&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;General Notes&lt;br /&gt;What is a pattern ?&lt;br /&gt;A Name, A Recurring problem with &lt;strong&gt;context&lt;/strong&gt;, A recommended Solution(or way ahead), &lt;strong&gt;Consequences and Alternatives&lt;/strong&gt;&lt;br /&gt;The bit a lot of people miss out is the Context and the Consequence. A pattern cannot be used irrespective of the context . This causes problems like 'Singletonitis'. A pattern always has some consequence. A pattern probably does have alternatives which are to be evaluated.&lt;br /&gt;A pattern need not always be up front design, you can arrive at many patterns with a judicious use of refactoring and some simple principles notably DRY.&lt;br /&gt;Patterns are also sometimes subsumed by the language or the platform (e.g. Factory in Visual Basic COM and Iterator in java) and some people refer to patterns as deficiency in the language / platform ( I dont agree!).&lt;br /&gt;Anyone who does anything with Design Patterns has to refer to Erich Gamma's et al book , and thats what I have based this on including the organisation of the patterns as Creational, Behavioral and Structural. Its quite difficult for novices (like me) to differentiate what between what constitutes a behavioral or structural pattern so dont bother right now.&lt;br /&gt;Also note that any Object oriented system has available to it the mechanisms of Polymorphism and Inheritance (Implementation of Interface). Therefore all diagrams of Design patterns will look similar in a lot of case. it is necessary to understand the nuance and differences and context.&lt;br /&gt;And lastly in a web project , differentiate between building a framework and solving a problem at hand. Its very easy to get carried away and over engineer and its as easy to under engineer, and it's also simple to shout TDD, refactoring , agile. Ultimately experience is what you use to decide whether you need a pattern upfront or later, Refactor or not. And anyone who tells you otherwise is either a manager or a consultant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-3111134611286609745?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/3111134611286609745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=3111134611286609745' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3111134611286609745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3111134611286609745'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/02/design-patterns-course.html' title='Design Patterns Course'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-5483472394033314852</id><published>2008-01-25T16:18:00.000-08:00</published><updated>2008-01-25T16:38:34.895-08:00</updated><title type='text'>Testing</title><content type='html'>You really appreciate the value of tests (especially regression) when you have to fix some code which is complex and is used in multiple places and you aren't sure of the various conditions under which it gets invoked (or even what the result should be). Unfortunately it is sometimes difficult to convince management. We asked and were denied initially anyway , for a separate environment to create and run tests. The separate environments were needed because of the extreme complexity of the business needed, in my opinion, an environment where the initial state is exactly known , otherwise there is no way to accurately predict the outcome of running time sensitive, old data sensitive scenarios. However the cost of maintaing said environment was deemed to be too high. Im not so sure. anyway we are getting an environment so yay, let the games begin.&lt;br /&gt;It's also at time like these that you realise , how out of touch with reality , the TDD/Agile/ JUnit testing  people that you see are , because they never seem to discuss anything but unit testing.&lt;br /&gt;I cant see unit test's adding much value to the system I work in , but oh what wouldn't I give for a set of repeatable integration and functional tests.&lt;br /&gt;Other than the really good Java Next Generation Testing book I havent seen the Testing books deal with real world stuff. (Did anyone else think that the Junit cookbook example of Money was representative of what people test in an automated way in real life)&lt;br /&gt;&lt;br /&gt;So here are the things that make the testing complicated&lt;br /&gt;a. The system run's on a cluster. Problems have been reported on the cluster , some of which have found to be environment related and some are code related. Would anything other than in container testing on representative environments find this out?.  This deals directly with the people advocating 'mocking' interfaces, not running in container, having fast running tests etc.&lt;br /&gt;b. One of the defects was caused when two unrelated processes ran at exactly the same time and on the same server of the cluster. The processes shared infrastructure code but were business wise and code wise unrelated. How would a test have found this out , other than sheer luck? Note that junit as a framework is really bad. Again this is not a complaint about JUnit, just that you dont see people discussing concurrent testing of unrelated data.&lt;br /&gt;c. A complex Architecture. A portal sends data asynchronously (JMS) to a WLI system which has multiple processes , which in turn needs a lot of system data (histories) to perform calculations, makes its business decisions using a set of business rules which are User Configurable(using a totally different system) and then persists this data to a database.&lt;br /&gt;Assuming you want to test that everything works end to end, is there any other way other than restoring the system to a known point in time(so you know what the out come should be?). The catch again is that running the same test on the exact same data might not still return the same results because the results are time sensitive (e.g. there is a different contract for 2007 as compared to 2008 so running the test in 2008 will give you different results).&lt;br /&gt;d. The results depend on the sequence of tests. This isn't a code problem , this is exactly how the business works. Other than creating different data for different cases , this is difficult to solve. In addition you do want to also test what happens when a particular sequence of events occur ( a claim is in , it is paid, the cheque is sent, the claim is adjusted, a new check is sent , the first one is returned, now assert). How is it that the unit testing folks shout themselves hoarse that tests should be independent of each other. I know I know , what I have described isn't a unit test.  But you see , the individual bits work. The sequence fails.&lt;br /&gt;Oh I can go on. But there is an India v/s Australia cricket match. Go India!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-5483472394033314852?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/5483472394033314852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=5483472394033314852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5483472394033314852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/5483472394033314852'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/01/testing.html' title='Testing'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-3097650606308538494</id><published>2008-01-25T16:06:00.000-08:00</published><updated>2008-01-25T16:17:43.440-08:00</updated><title type='text'>Debugging</title><content type='html'>Due to circumstances beyond our control , we've had to take up fixing someone else's code. The business rules are complex (which means the code must be so). There are no existing tests (this is a consequence of both the complex rules and a complex architecture , the latter could be simplified if it were not for the fact that the project is years late). Now the TDD guys are probably jumping up and down at this stage , pointing out that the lack of tests is the reason why everything is so complex , just ignore them , we'll get to these folks later. The bottom line is there are no tests, we are trying to create some regression tests, that will take time , meanwhile there are still bugs to be resolved. I was assigned one of them.&lt;br /&gt;It took me 2 hours to setup the environment . Ones a weblogic portal domain and Ones a weblogic integration domain. The build for the portal takes about 30 minutes after which weblogic  workshop duly crashes. I have to point my servers to a configuration other than their default which needs me to mess around manually. It takes another hour to understand what the defect is. it takes some more time to verify that the tester is indeed right, the system is doing something wrong. It takes some time to identify the areas of code that are possibly the cause. it takes a couple of hours to understand the nuances in the mostly undocumented code.&lt;br /&gt; I then have to go and ask another dev, whether the testers expected results are correct, and it turns out they aren't. There is a defect and what the system currently does is wrong , but what should the system do is undocumented and unknown. We could make a guess but this impacts other systems so we need them to confirm. A meeting is scheduled.&lt;br /&gt;The meeting lasts 2 hours. Some issues are resolved, Some new ones are raised. Some have to be followed up with other people. Armed with some more knowledge I look through the code. I get a sudden inspiration, I test out two scenarios , it looks like I'm right.&lt;br /&gt;&lt;br /&gt;The defect is fixed by modifying all of two lines of code. Total time to fix defect ? 1.5 days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-3097650606308538494?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/3097650606308538494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=3097650606308538494' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3097650606308538494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/3097650606308538494'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2008/01/debugging.html' title='Debugging'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-2093026599304771006</id><published>2007-02-14T08:56:00.001-08:00</published><updated>2007-05-07T12:48:48.665-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><title type='text'>Useful links</title><content type='html'>&lt;a href="http://dev2dev.bea.com/pub/a/2004/01/pg_flows.html"&gt;Advanced Pageflow&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dev2dev.bea.com/blog/srengan/archive/2006/10/cm_api_92_unlea.html"&gt;CM API usage example&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dev2dev.bea.com/pub/a/2006/11/effective-exceptions.html"&gt;Faults  and Contingencies&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dev2dev.bea.com/pub/a/2005/01/wlst_offline.html"&gt;WLST offline&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-2093026599304771006?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/2093026599304771006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=2093026599304771006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2093026599304771006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/2093026599304771006'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2007/02/useful-links.html' title='Useful links'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-451711759546671422</id><published>2007-02-14T08:46:00.000-08:00</published><updated>2009-10-20T22:12:24.336-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Weblogic Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><title type='text'>Weblogic Portal interview questions</title><content type='html'>The following are the Portal interview questions that ive used or kept or have been asked(in no particular order , and no answers either :) )&lt;br /&gt;I do not include questions (e.g. what is a nested pageflow) that can be answered with google.&lt;br /&gt;Also see &lt;a href="http://theworkaholic.blogspot.com/2009/10/weblogic-portal-interview-questions-ii.html"&gt;Weblogic Portal interview questions - II&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In what situations can you not use a UUP ?. What factors determine choosing a UUP?&lt;/li&gt;&lt;li&gt;What are the different techniques you can use for Inter Portlet Communications?. What are the pros and cons of each technique?.&lt;/li&gt;&lt;li&gt;Would you choose 1 desktop with entitlements or multiple desktops? Why?&lt;/li&gt;&lt;li&gt;What are the options for security in Weblogic Portal?&lt;/li&gt;&lt;li&gt;Can you change a LookAndFeel at runtime ?, if so what are the alternatives?&lt;/li&gt;&lt;li&gt;What is the impact of using AJAX in a portlet (out of the box or otherwise)?&lt;/li&gt;&lt;li&gt;Why should pageflow variables be serializable?&lt;/li&gt;&lt;li&gt;If your using a file repository for content and you have a webserver in front of the application servers who serves the static files?&lt;/li&gt;&lt;li&gt;When do you use the refresh action?&lt;/li&gt;&lt;li&gt;What happens if the validate method of your form bean throws an exception&lt;/li&gt;&lt;li&gt;How do you use the struts validation framework with BEA pageflows?&lt;/li&gt;&lt;li&gt;The BEA pageflow documentation mentions that there is only 1 current pageflow. And that the current pageflow is destroyed when a new one is accessed. is that accurate?&lt;/li&gt;&lt;li&gt;What all features should a screen scraping portlet possess? &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;To be continued...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-451711759546671422?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/451711759546671422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=451711759546671422' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/451711759546671422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/451711759546671422'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2007/02/weblogic-portal-interview-questions.html' title='Weblogic Portal interview questions'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-1865764147749548852</id><published>2007-02-13T06:48:00.000-08:00</published><updated>2007-02-13T06:55:40.387-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='weblogic'/><title type='text'>Weblogic debug flags</title><content type='html'>Reproduced from &lt;a href="http://dev2dev.bea.com/blog/hoos/archive/2007/01/weblogic_server.html"&gt;Hussein Badakhchani's Blog&lt;/a&gt;&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;  and comments&lt;br /&gt;weblogic debug flags(8.1)&lt;br /&gt;&lt;strong&gt;IIOP&lt;/strong&gt;&lt;br /&gt;weblogic.iiop.ots&lt;br /&gt;weblogic.iiop.transport&lt;br /&gt;weblogic.iiop.marshal&lt;br /&gt;weblogic.iiop.startup&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;JDBC/Data Sources&lt;/strong&gt;&lt;br /&gt;weblogic.JDBCConn&lt;br /&gt;weblogic.JDBCSQL&lt;br /&gt;weblogic.JDBCConnStackTrace&lt;br /&gt;&lt;br /&gt;  &lt;strong&gt;JMX/Deployment&lt;/strong&gt;&lt;br /&gt;weblogic.commoAdmin&lt;br /&gt;weblogic.commoProxy&lt;br /&gt;weblogic.deployerRuntime&lt;br /&gt;weblogic.MasterDeployer&lt;br /&gt;weblogic.deployTask&lt;br /&gt;weblogic.deployHelper&lt;br /&gt;weblogic.MasterDeployer&lt;br /&gt;weblogic.OamDelta&lt;br /&gt;weblogic.OamVersion&lt;br /&gt;weblogic.slaveDeployer.semaphore&lt;br /&gt;weblogic.slaveDeployer&lt;br /&gt;weblogic.ConfigMBean&lt;br /&gt;weblogic.ConfigMBeanEncrypt&lt;br /&gt;weblogic.ConfigMBeanSetAttribute&lt;br /&gt;weblogic.management.DynamicMBeanImpl&lt;br /&gt;weblogic.management.DynamicMBeanImpl.setget&lt;br /&gt;weblogic.mbeanProxyCache&lt;br /&gt;weblogic.mbeanDelete&lt;br /&gt;weblogic.mbeanQuery&lt;br /&gt;weblogic.MBeanInteropList&lt;br /&gt;weblogic.mbeanProxy&lt;br /&gt;weblogic.registerMBean&lt;br /&gt;weblogic.getMBeanInfo&lt;br /&gt;weblogic.getMBeanAttributes&lt;br /&gt;weblogic.addDependenciesRecursively&lt;br /&gt;weblogic.MBeanListener&lt;br /&gt;weblogic.application&lt;br /&gt;weblogic.deployer&lt;br /&gt;weblogic.appPoller&lt;br /&gt;weblogic.appManager&lt;br /&gt;weblogic.BootstrapServlet&lt;br /&gt;weblogic.fileDistributionServlet&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Application Deployment&lt;/strong&gt;&lt;br /&gt;weblogic.J2EEApplication&lt;br /&gt;weblogic.application&lt;br /&gt;weblogic.appPoller&lt;br /&gt;weblogic.appManager&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;JTA&lt;/strong&gt;&lt;br /&gt;weblogic.JTAGateway&lt;br /&gt;weblogic.JTAGatewayStackTrace&lt;br /&gt;weblogic.JTA2PC&lt;br /&gt;weblogic.JTA2PCStackTrace&lt;br /&gt;weblogic.JTAHealth&lt;br /&gt;weblogic.JTAPropagate&lt;br /&gt;weblogic.JTARecovery&lt;br /&gt;weblogic.JTAXA&lt;br /&gt;weblogic.JTAXAStackTrace&lt;br /&gt;weblogic.JTAResourceHealth&lt;br /&gt;weblogic.JTAMigration&lt;br /&gt;weblogic.JTARecoveryStackTrace&lt;br /&gt;weblogic.JTANaming&lt;br /&gt;weblogic.JTATLOG&lt;br /&gt;weblogic.JTALifecycle&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;EJB&lt;/strong&gt;&lt;br /&gt;weblogic.ejb.cache.debug&lt;br /&gt;weblogic.ejb.cache.verbose&lt;br /&gt;ejb.enableCacheDump&lt;br /&gt;weblogic.ejb20.cmp.rdbms.debug&lt;br /&gt;weblogic.ejb20.cmp.rdbms.verbose&lt;br /&gt;weblogic.ejb20.persistence.debug&lt;br /&gt;weblogic.ejb20.persistence.verbose&lt;br /&gt;weblogic.ejb20.compliance.debug&lt;br /&gt;weblogic.ejb20.compliance.verbose&lt;br /&gt;weblogic.ejb.deployment.debug&lt;br /&gt;weblogic.ejb.deployment.verbose&lt;br /&gt;weblogic.ejb20.dd.xml&lt;br /&gt;weblogic.ejb.deployer.debug&lt;br /&gt;weblogic.ejb.deployer.verbose&lt;br /&gt;weblogic.ejb.verbose.deployment&lt;br /&gt;weblogic.ejb20.ejbc.debug&lt;br /&gt;weblogic.ejb20.ejbc.verbose&lt;br /&gt;weblogic.ejb.runtime.debug&lt;br /&gt;weblogic.ejb.runtime.verbose&lt;br /&gt;weblogic.ejb20.jms.poll.debug&lt;br /&gt;weblogic.ejb20.jms.poll.verbose&lt;br /&gt;weblogic.ejb20.security.debug&lt;br /&gt;weblogic.ejb20.security.verbose&lt;br /&gt;weblogic.ejb.locks.debug&lt;br /&gt;weblogic.ejb.locks.verbose&lt;br /&gt;weblogic.ejb.bean.manager.debug&lt;br /&gt;weblogic.ejb.bean.manager.verbose&lt;br /&gt;weblogic.ejb.pool.InstancePool.debug&lt;br /&gt;weblogic.ejb.pool.InstancePool.verbose&lt;br /&gt;weblogic.ejb.swap.debug&lt;br /&gt;weblogic.ejb.swap.verbose&lt;br /&gt;weblogic.j2ee.dd.xml&lt;br /&gt;&lt;br /&gt; &lt;strong&gt;General&lt;/strong&gt;&lt;br /&gt;weblogic.debug&lt;br /&gt;weblogic.kernel.debug&lt;br /&gt;weblogic.debug.DebugConnection&lt;br /&gt;weblogic.debug.DebugRouting&lt;br /&gt;weblogic.debug.DebugMessaging&lt;br /&gt;weblogic.debug.isLogRemoteExceptionsEnabled&lt;br /&gt;weblogic.StdoutDebugEnabled&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;WLI&lt;/strong&gt;&lt;br /&gt;wlc.debug.signature&lt;br /&gt;wli.bpm.client.security.debug&lt;br /&gt;wli.bpm.studio.timeprocessor.debug&lt;br /&gt;wli.bpm.studio.debug&lt;br /&gt;wli.bpm.server.common.timedevent.debug&lt;br /&gt;wli.bpm.server.common.xmltemplate.debug&lt;br /&gt;wli.bpm.server.eventprocessor.addrmsgdebug&lt;br /&gt;wli.bpm.server.eventprocessor.debug&lt;br /&gt;wli.bpm.server.jms.debug&lt;br /&gt;wli.bpm.server.plugin.debug&lt;br /&gt;wli.bpm.server.workflow.debug&lt;br /&gt;wli.bpm.server.businesscalendar.debug&lt;br /&gt;wli.bpm.server.busop.debug&lt;br /&gt;wli.bpm.server.workflow.action.taskduedate.debug&lt;br /&gt;wli.bpm.server.workflow.timedevent.debug&lt;br /&gt;wli.bpm.server.xml.debug&lt;br /&gt;wli.bpm.server.xslt.debug&lt;br /&gt;wli.bpm.server.workflow.start.debug&lt;br /&gt;wli.bpm.server.workflowprocessor.debug&lt;br /&gt;wli.common.server.errorlistener.debug&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Messaging Bridge&lt;/span&gt;&lt;br /&gt;-Dweblogic.debug.DebugMessagingBridgeStartup=true   -Dweblogic.debug.DebugMessagingBridgeRuntime=true  And two others for stdout and stderr : -Dweblogic.Stdout= -Dweblogic.Stderr=&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SSL&lt;/span&gt;&lt;br /&gt;-Dweblogic.security.SSL.verbose=true -Dssl.debug=true&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;-9.x  available via console plus&lt;/span&gt;&lt;br /&gt;webservices:  -Dweblogic.wsee.verbose=*&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;6.x,7.x&lt;/span&gt;&lt;br /&gt;http://wldj.sys-con.com/read/42733.htm&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;RMI debug flags&lt;/span&gt;&lt;br /&gt;java.rmi.server.logCalls=true&lt;br /&gt;sun.rmi.loader.logLevel=[BRIEF|VERBOSE]&lt;br /&gt;sun.rmi.server.exceptionTrace&lt;br /&gt;sun.rmi.server.logLevel=[BRIEF|VERBOSE]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-1865764147749548852?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/1865764147749548852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=1865764147749548852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1865764147749548852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/1865764147749548852'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2007/02/weblogic-debug-flags.html' title='Weblogic debug flags'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-116395377466761630</id><published>2006-11-19T08:21:00.000-08:00</published><updated>2007-02-13T06:56:44.043-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>More straws</title><content type='html'>&lt;a href="http://jeffsutherland.com/scrum/2006/11/scrum-supports-cmmi-level-5.html"&gt;http://jeffsutherland.com/scrum/2006/11/scrum-supports-cmmi-level-5.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jeffsutherland.com/scrum/2006/11/is-cmmi-worth-doing.html"&gt;http://jeffsutherland.com/scrum/2006/11/is-cmmi-worth-doing.html&lt;/a&gt;&lt;br /&gt;From the inventor of scrum&lt;br /&gt;(Disclaimer i am working in a CMM Level 5 company and its possible indeed probable i am biased)&lt;br /&gt;So the agile management folks see value in CMM level 5 principles. After all what could be incorrect about&lt;br /&gt;Level 1 - Uncertainty. Success depends on individual effort.&lt;br /&gt;Level 2 - Awakening. Basic project management practices are established.&lt;br /&gt;Level 3 - Enlightenment. Standard process throughout organization.&lt;br /&gt;Level 4 - Wisdom. Detailed metrics are collected and evaluated.&lt;br /&gt;Level 5 - Certainty. Continuous process improvement via metrics feedback.&lt;br /&gt;Wouldnt everyone want to be level 5 , certain their project succeeds?&lt;br /&gt;But isnt agile about people above process?&lt;br /&gt;Doesnt agile tacitly imply that if the people arent good no process is going to save anything?&lt;br /&gt;Certainly there isnt anything in agile that forbids collection of metrics and forbids improvement. Indeed doesnt the automation of everything in sight actually allow you to do this.&lt;br /&gt;But but but and herein lies the problem, the practice of collecting metrics is so perverted (see the timesheets which have a task called filling in timesheet) that almost always means that people will fudge it.&lt;br /&gt;It also looks like agile management consultants have discovered there is money to be made by coaching people to be agile scrum cmmi pcmm bs577 compliant. Or whatever.&lt;br /&gt;So will the agilisits be enlightened? Does a standard process have more value than a tweaked one? Whatever happened to the these are guidelines and must be changed for your project, use whatever works for you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-116395377466761630?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/116395377466761630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=116395377466761630' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/116395377466761630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/116395377466761630'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2006/11/more-straws.html' title='More straws'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-116333349406173271</id><published>2006-11-12T04:05:00.000-08:00</published><updated>2007-02-13T07:04:57.591-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Agile no more</title><content type='html'>Its amazing to see how developer friendly practices are perverted into management friendly practices as soon as a pack of managers are let loose on them.Right so lets begin at the beginning  Individuals and interactions over processes and tools   Working software over comprehensive documentation   Customer collaboration over contract negotiation   Responding to change over following a plan (&lt;a href="http://www.agilemanifesto.org/"&gt;http://www.agilemanifesto.org&lt;/a&gt;)While we could quible over whether we collaborate with customers or negotiate with them , its fairly reasonable to assume that no software engineer is going to disagree with the spirit of what was said here.All of the above principles are developer friendly. No more follow that CMM level 5 process, No more according to my project plan we should have finished 53.23% percent of project. are we there yet?But look agile has crossed the chasm and what do we haveAgile consultants who have the "you must tailor agile to meet your needs" that means you need an agile coach or a scrum master whatnot because evidently if you tried to do it yourself your project would fail because you would do agile wrong.Oh look agile projects do need management. And it must be something new otherwise how would we consultants ever earn money?Heres a new management technique. Lets call it Scrum. We cant obviously have a position called Project Manager , lets call it scrum master. Lets not call it a requirements document, lets call it a product backlog. Lets not call it an iteration , lets call it a sprint. Oh yes how about burndown charts, yep sounds like something people would pay money to be taught what it is. Oh and wait we need to know what our teammates are upto every minute. Lets ask for status updates every day. Oh and we need to have data on the minutest of things. Hmm we cant call it a timesheet but we'll make them fill up the hours for every minute task and we'll make them constantly reestimate each task.Ok so thats an exaggeration.But think about it. Say the functionality on a website was show orders for a user. What would a developer say (lets assume the overall architecture and software and platforms have been decided). Mostly something like ok it would take about a week for me to do it.  If you fell behind you 'd sit up for 2 hours more if you were ahead you'd quit and go home early. In about a week you'd be done if you were reasonably competent. Developer friendly? Id think so. if there were problem you'd escalate as soon as you knew of it. If the problem was technical you'd ask your peers at lunch or tea.But thats not what's being practised.1 week as a coarse estimate wont do any more. You have to provide finer tasks so that you know if you are in red. You have to track at an hour basis for the tasks. You have to give an update every day. You have to work uniformly for 8 hours every day because supposedly that increases productivity. Bah. Anyone who's coded knows that if the problem is interesting and you've started on it , you wont stop unless you've solved the problem Or atleast its that way for some people.Not all people are alike.And so we come to the original manifesto. For the agile projectsIs it individual and interactions over processes and tools ? Probably not. look around the debates in agile . To pair program or not to (process) , to TDD or not to (process), unit test all code (process),  daily standup calls(process), use wiki for collaboration (tool), use junit(tool) etc etc&lt;br /&gt;Working software over comprehensive documentation ? Product/Sprint Backlogs, Burn down charts, User stories (all documentation)&lt;br /&gt;Customer collaboration over contract negotiation ? Ambiguous at best. And certainly i have yet to see any agile consultants who havent negotiated contracts.&lt;br /&gt;Responding to change over following a plan? No more and no less than before, perhaps evidenced by the fact that the manifesto is signed in 2001 and 5 years hence there has been no change to it. Lessons learnt in the 5 years have definitely not caused the manifesto to change. Rather any failures are met with the standard "you arent doing it right"&lt;br /&gt;Perhaps the problem is in the first item in the process. Individuals. And individuals are flawed and biased.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-116333349406173271?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/116333349406173271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=116333349406173271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/116333349406173271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/116333349406173271'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2006/11/agile-no-more.html' title='Agile no more'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-115668238987108876</id><published>2006-08-27T05:38:00.000-07:00</published><updated>2007-02-13T07:05:13.148-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>More Agile</title><content type='html'>Burst out laughing when I read&lt;br /&gt;“Soon all of our singletons were composite, we could use the factory method on our abstract factory to get the prototype of the builder which would make a proxy for the decorated adapter that acted as a facade for the visitor which took us to see all of our singletons”- &lt;a href="http://jroller.com/page/rolsen?entry=turn_it_up_to_11"&gt;http://jroller.com/page/rolsen?entry=turn_it_up_to_11&lt;/a&gt;&lt;br /&gt;Since it reminds me of a certain project I was in where the chief designers had obviously come out of a design patterns course and so there were *Factory aplenty which then lead to the creation of a class named FactoryFactory and the clients of this API who ofcourse had their own factory came up with FactoryFactoryFactory. Ok the last class is fictional , but the one before that is an actual class.&lt;br /&gt;And so yes the latest rage is Agile and Scrums and what nots. I remember reading Kent Beck’s book on extreme programming about 5 years ago when agile had not yet caught up here in India, agreeing vehemently on the accept change and disagreeing just as vehemently on pair programming (some people interpret this as side by side programming, a practice I wholeheartedly endorse , and not just for technical reasons, its how I met my wife to be :-) )&lt;br /&gt;As the years went by and I saw more and more of the strict waterfall model , the im not going to start design till requirements are signed of, im not going to start development till design is signed off, I realized the agilest were right , waterfall like practices are no way to run a project. Agile was the way to go. And though we didn’t practice all the various XP practices or Scrum or whatever, most projects I worked on were pretty much flexible, with changes being accepted after the date for code freeze (which magically thawed)&lt;br /&gt;Oh just to clarify , we are a service/project oriented organization , providing services to various clients. The client I work with now has decided to go Agile in a major way and to impress the client agile training is now mandatory for everyone in our group in our organization. And ive kept up with some of the articles that the agilists keep publishing. And so the inevitable conclusion. There is no practice in the world that people cant screw up.&lt;br /&gt;So lets see where do we start.&lt;br /&gt;First the proponents of agile itself. While they make the right noises (Each process must be tailored to what works for you), the answers given most of the time is ,(to quote cedric beust) “if you aren’t getting benefits from agile , you aren’t doing it right.”&lt;br /&gt;Second the insistence by some on absolutely silly practices. Like Code the test first before you write the code. I cant and don’t want to code tests that don’t bloody well compile , I have to define the interfaces and classes implementing those first atleast! Though of course testing is good , automated tests are better, unit tests are ok, mock tests are ok, Integration tests are worth their value in gold. But try getting some agilist to talk about tests other than unit tests.&lt;br /&gt;Then we have the silly rules that follow from the above. You must have 90% coverage in your tests cases, otherwise code is rejected. Heres a thought experiment. Write a function doubleIt , return the value 4 always and write a test case which passes in the value 2. You have voila 100% coverage. Beat that. No need to write more tests. If you impose silly rules , developers will work around them.&lt;br /&gt;And then we have the other problems. Daily status calls, not exceeding 15 mins. Must be at the start of the day. Ok cool. Umm the delivery head is US based, the customer in UK and the dev team in India. Whats the start of the day? Oh agile doesn’t work so well for distributed teams! Well what do I do then go back to waterfall? Stupid.&lt;br /&gt;And the ofcourse the famous if you aren’t doing practice x, you aren’t agile.&lt;br /&gt;I think I prefer the time when in a project of duration of 1 month you could relax for 15 days and then work double for the next 15 instead of work uniformly for the 30 days.&lt;br /&gt;Though people may say that quality in the latter case is better, I don’t think that’s necessary.&lt;br /&gt;I don’t think agile works in the real world. Distributed teams are a fact of life. Multi vendor projects with conflicting interests are a fact of life too. I suppose agile would work with a closely knit team. But that’s fast becoming an exception in the areas we work.&lt;br /&gt;And with new processes and positions (like agile coach) the Agile methodology is becoming as rigid as the other processes.&lt;br /&gt;And a final thought whats remained the rule in software , good people can make any process work, incompetents can make any process fail.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-115668238987108876?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/115668238987108876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=115668238987108876' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/115668238987108876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/115668238987108876'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2006/08/more-agile.html' title='More Agile'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-114942623113797918</id><published>2006-06-04T06:03:00.000-07:00</published><updated>2007-02-13T07:05:27.146-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Agile</title><content type='html'>The other day I got a ppt from a friend who got it from someone else about a project in my company which is a “success” because how they implemented “agile methodologies” and how it helped and the practices they followed with general patting of backs and lessons learnt and improvements still to be made.&lt;br /&gt;It’s a 75 slide power point.&lt;br /&gt;Get the picture?&lt;br /&gt;Or lets see the Extreme programming principles. On one hand embrace change and on the other you must follow x,y,z to have a successful project(with no guarantees of success). What happens if you don’t pair program or do test driven development or whatever else is the latest breakthough in software engg? Is it that you don’t embrace change?&lt;br /&gt;I think agile is best described by uncle bob , “never be blocked”. And once you accept that, the agile manifestos, the programming principles the slide guides aren’t all that necessary. True they might help, but the problem is any rigid process (agile extreme or otherwise) causes blocks.&lt;br /&gt;Write junits for everything. Unit test are really low value for money. Integration tests are very hard( especially if it’s a distributed system, developed by multiple disparate teams )over space and time. All the wonderful stubs and mocks so loved by the TDD guys fail when the stub and mocks are replaced by the actual system. Which isn’t to say stubs aren’t good, but they give you a false sense of security. And can hide flaws. For e.g. There was a defined web service interface. It wasn’t ready we mocked it. All was well. Till we ran it with real data. Turns out we get stuff like ##YOUSHOULDNTSEETHIS## the xml structure is the same , the web service has the same interface but surprisingly none of us thought to write stubs and mocks that returned elements with junk values.Or what to do in that case or even how to identify them.&lt;br /&gt;You can and should violate principles if the need arises. That’s agile. Embrace change. a&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-114942623113797918?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/114942623113797918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=114942623113797918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/114942623113797918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/114942623113797918'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2006/06/agile.html' title='Agile'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-113431629169100474</id><published>2005-12-11T07:51:00.000-08:00</published><updated>2007-02-13T07:05:36.103-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>The Fallacies of Design</title><content type='html'>The Fallacies of Design&lt;br /&gt;While reading the various UML/Pattern/Architecture/OO/XP/TDD books and literature, I think most authors forget some of the basic maladies that plague software projects. Or perhaps because there are no solutions for the problems, it is best to ignore them. So far there have been very few insurmountable problems as regards to the technologies involved in projects that I have worked on. They have always been workarounds , tactical pathworks and other hacks. But there are the other issues which can derail a project.&lt;br /&gt;So here are the various fallacies I have seen&lt;br /&gt;&lt;ol&gt;&lt;li&gt;There is a best solution that solves your problems. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Systems that you need to integrate/interact with can be changed to implement the best possible solution&lt;/li&gt;&lt;br /&gt;&lt;li&gt;People within the project will cooperate with you. People outside the project will cooperate with you&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The People defining the requirements know what they want. Once a requirement is signed of by said rule, it wont change&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Budget is infinite, Time is infinite&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Managers can manage, Designers can design, Analysts can analyze and coders can code. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The solution to any problem is a pattern/platform/approach/methodology&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If the test cases pass and code coverage is &amp;gt; x% then there wont be problems in the wild&lt;/li&gt;&lt;br /&gt;&lt;li&gt;People will always tell the truth&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Murphys law does not apply to software.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;None of these fallacies are technical. They aren’t meant to be. Its rarely the technology that derails a project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-113431629169100474?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/113431629169100474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=113431629169100474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/113431629169100474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/113431629169100474'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/12/fallacies-of-design.html' title='The Fallacies of Design'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-113146517004719264</id><published>2005-11-08T07:52:00.000-08:00</published><updated>2008-02-01T16:50:05.253-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Design Patterns v/s Experience</title><content type='html'>While reading through TestNG and comparing it with JUnit, it is obvious that TestNG is far simpler to use and at first glance looks to be designed better (or has more features). Note I haven’t written a single TestNG test yet.&lt;br /&gt;And I remembered reading , when people complained about the limitations of JUnit that JUnit was designed as a framework that could be extended. And how JUnit had used all sorts of design patterns.&lt;br /&gt;Which leads us to Design Patterns v/s Experience question. I do not suggest these two are mutually exclusive. The comparison of JUnit and TestNG is not strictly fair, and neither is this a feature by feature comparison, nor an indictment of design pattern approaches. Its simply that having JUnit (and its varied extensions around) allowed Cedric to create a better framework. Like not having to implement a class or interface for your tests. The different ways of running setup (as opposed to the design pattern used by Gamma and co.) . And while a catalog of Design Patterns exist, how do you quantify or catalog the Experience that allows you to select the correct Design Pattern?&lt;br /&gt;Experience also teaches you when design patterns need not be used. (oh yes there are cases, but I leave that for a separate entry).&lt;br /&gt;And if you had to choose a candidate with Design patterns on his CV(All candidates know factory,singleton,value object, dao and session façade) or one who seemed to have the experience, choose the guy with experience (This has nothing to do with 6 yrs experience and no DP in CV!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-113146517004719264?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/113146517004719264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=113146517004719264' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/113146517004719264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/113146517004719264'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/11/design-patterns-vs-experience.html' title='Design Patterns v/s Experience'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-111493523037874120</id><published>2005-05-21T21:43:00.000-07:00</published><updated>2007-02-13T07:07:00.484-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ethics'/><title type='text'>Youth And Responsibility</title><content type='html'>Its obvious to anyone who thinks about such things that the only hope for the future are the youth. The big picture aside, lets look at youth only in the context of the workplace. Its also painfully evident that no one trusts the young trainees just out of the trainee program.&lt;br /&gt;We are of course polite. They dont have enough experience we say, we cant risk it - what if they screw up on production?. We(the experienced people, the guys who have seen it all) can't spend all our time reviewing what the trainees are delivering. In other words it is easy to find rational arguments which prevent us from delegating responsibility/tasks to the young 'uns.&lt;br /&gt;The plain truth is that we don't trust them. Or we trust that they will screw  up.&lt;br /&gt;Which is a sorry state of affairs.&lt;br /&gt;I need to break out of this mental block . And I think I'm still someone who trusts the younger  people around him a lot more than others.&lt;br /&gt;But it has to improve&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-111493523037874120?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/111493523037874120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=111493523037874120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111493523037874120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111493523037874120'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/05/youth-and-responsibility.html' title='Youth And Responsibility'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-111434227966360262</id><published>2005-05-01T02:18:00.000-07:00</published><updated>2007-02-13T07:06:15.097-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='management'/><title type='text'>The Anarchist Management Model</title><content type='html'>One of the things that keeps occupying my thoughts these days is how much that we learn from life can be applied to our work.&lt;br /&gt;One of the major problems in work can be summarised as Management. Most non managers would not hesitate in calling Management evil , and only perhaps were we really feeling charitable would we call Management a necessary evil. But Managment persists as a practice , even worse you have younger generations(am i really this old?) growing up wanting to be managers. You have people joining the project stating that they want a management role.&lt;br /&gt;As such I'm against all sorts of management in principle. I think this has to do with the fact that as a form of governance I prefer Anarchy. And currently Management is a pseudo democratic dictatorship. You dont really have a say on who is your manager (hence a sort of dictatorship) but perhaps results /feedback can get the manager removed.&lt;br /&gt;Id like to see a project where people take responsibility for their actions. Divide the work amongst themselves based on their competencies. Set targets for themselves and meet them. Resolve their problems without needing outside intervention.&lt;br /&gt;Could it Happen ?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-111434227966360262?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/111434227966360262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=111434227966360262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111434227966360262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111434227966360262'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/05/anarchist-management-model.html' title='The Anarchist Management Model'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-111312246195905005</id><published>2005-04-10T01:34:00.000-07:00</published><updated>2007-02-13T07:06:02.622-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Culture and Design</title><content type='html'>Does the culture we have been brought up with affect the design work we do?&lt;br /&gt;Case In point.&lt;br /&gt;One of the clients of my company is spending large amounts of money to attain homogenity in the technology/platforms/systems it uses to avoid the integration problems that arise with heterogenous systems.&lt;br /&gt;My personal preference has always been to develop systems independently using whatever is best for that system. And then figure out ways to integrate them.&lt;br /&gt;Both approaches have their shortcomings and advantages of course.&lt;br /&gt;&lt;br /&gt;Im wondering if the fact that diversity that is so much a part of Indian life has anything to do with my preference. If so i'm grateful for it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-111312246195905005?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/111312246195905005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=111312246195905005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111312246195905005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111312246195905005'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/04/culture-and-design.html' title='Culture and Design'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-111312204660458193</id><published>2005-04-10T01:26:00.000-07:00</published><updated>2007-02-13T07:06:31.196-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='interviews'/><title type='text'>Interviews</title><content type='html'>One of the things that is part of my my workstack is obliging Recruitment whenever they want some J2EE interviews conducted.&lt;br /&gt;It is a highly painful experience.&lt;br /&gt;On one side we have the questions that we are given to ask by Theoreticians who seem to be detached from real world programming (what is the output of i++ + ++i or how many overloaded constructors does the File object have - note these arent really questions we are supposed to ask , but you get the idea) .&lt;br /&gt;On the other side we have the candidates. It looks like they come prepared to answer questions like the above. And because I always begin with what are the technical details of your project and what did you work on, 9 times out of 10 the candidate looks back with a blank stare. Or provides some inane details like There is a login screen , the user enters his password and is taken to his homepage. The End. I am not alone in this regard. Other people from my company have expressed similar sentiments. Perhaps the reason is no good candidates are applying to my company :-) .&lt;br /&gt;This actually leaves only one way out if we want competent resources. Hire people out of college. Train them and then mentor them.&lt;br /&gt;It remains to be seen how successful this will be&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-111312204660458193?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/111312204660458193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=111312204660458193' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111312204660458193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111312204660458193'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/04/interviews.html' title='Interviews'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10045102.post-111072050259408933</id><published>2005-03-13T05:17:00.000-08:00</published><updated>2007-02-13T07:06:43.098-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ethics'/><title type='text'>Loyalty</title><content type='html'>Do you remember the time you were in school? The time when your school was the bestest there was , when all the people in your school were smarter than any other school , where the grounds were better to play in than in anyone else's school, where the teachers were the best and kindest, where the principals were stern but what the heck you liked them anyway.&lt;br /&gt;I do.&lt;br /&gt;One of the things you learnt in school was loyalty and that loyalty begets loyalty. And there was a thing called Honour.Do you remember the time the teacher asked who did whatever and everyone knew but no one said a word.? Atleast my school(and with that i include the campus , the teachers and my fellow students) did try to teach me that. But then i did tell you it was the best school.&lt;br /&gt;One of the first things that struck me in the induction speech when i joined by company (5.5 years back) was the thing someone from senior management said. He said You should not be loyal to the company. He said the company does not even want your loyalty. It will do what is best for itself and you should do what is best for yourself. He went on to refer to the practice in my company of giving &lt;em&gt;long&lt;/em&gt; service awards at the end of 3 years and joked about it.&lt;br /&gt;The Achieving excellence session went on to teach you new keywords WIIFM WIIFU (whats in it for me , whats in it for us)&lt;br /&gt;At that time i would rather listen to If(Rudyard Kipling)&lt;br /&gt;&lt;em&gt;If you can talk with crowds and keep your virtue, &lt;/em&gt;&lt;br /&gt;&lt;em&gt;Or walk with kings - nor lose the common touch; &lt;/em&gt;&lt;br /&gt;I resolved that this was a case of keeping my virtue while walking with the crowd and thefact that the company doesnt care for my loyalty does not in any way prevent me from being loyal.&lt;br /&gt;I suspect that i should have bowed to experience instead of indulging in youthful idealism.&lt;br /&gt;So much so that the fact that i have stuck with my company for 5 and a half years is now a liability. Supposedly IT HR  people feel that if a software engineer sticks in the same company for more than two years there is something wrong with him - lack of ambition, initiative whatever.&lt;br /&gt;So why am i still in my company&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10045102-111072050259408933?l=theworkaholic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://theworkaholic.blogspot.com/feeds/111072050259408933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10045102&amp;postID=111072050259408933' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111072050259408933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10045102/posts/default/111072050259408933'/><link rel='alternate' type='text/html' href='http://theworkaholic.blogspot.com/2005/03/loyalty.html' title='Loyalty'/><author><name>Deepak Shetty</name><uri>http://www.blogger.com/profile/04324456947895848248</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
