| <?xml version="1.0"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <document> |
| |
| <properties> |
| |
| <title>Extending JMeter</title> |
| |
| </properties> |
| |
| <body> |
| |
| <section name="JMeter Extension Scenario"> |
| <p>The purpose of this tutorial is to |
| describe the general steps involved in a JMeter extension scenario. The |
| <a href="index.html">JMeter documentation</a> describes what must be done on a microscopic level but does |
| not provide an overall idea of the process. That is the intent of this brief |
| article. The JMeter extension documentation should be consulted for details.</p> |
| <P>The high level procedure followed these steps. |
| </P> |
| <OL> |
| <LI><A href="#planning">Planning</A></LI> |
| <LI><A href="#config">Code the configuration |
| object</A> </LI> |
| <LI><A href="#config-gui">Code the configuration |
| GUI object</A> </LI> |
| <LI><A href="#control">Code the controller |
| object</A> </LI> |
| <LI><A href="#control-gui">Code the controller GUI |
| object</A> </LI> |
| <LI><A href="#sampler">Code the Sampler object</A> </LI> |
| |
| <LI><A href="#installation">Install your |
| extension</A> </LI> |
| <LI><A href="#tips">Tips</A> </LI></OL> |
| <H2><A name="planning">Planning</A></H2>I've found planning a JMeter extension to |
| involve three aspects: |
| |
| <OL> |
| <LI>What you want the sampler to do </LI> |
| <LI>What information is needed for the sampler to work </LI> |
| <LI>How the information is to be acquired from the user </LI></OL> |
| <P>You'll notice that the coding steps are somewhat backwards from the planning |
| steps (the sampler is coded last). The coding order was determined by which |
| classes could be tested earliest. The config/gui can be tested in isolation. The |
| controller can be tested with the config element. Neither of these requires a |
| Sampler to be present initially. </P> |
| <H2><A name="config">Configuration Object</A></H2>The role of the configuration |
| object is to supply parameters to the Sampler that can vary from sample to |
| sample. In the case of the <TT>UrlConfig</TT> object, this would be information |
| such as the host name, port, GET or PUT and various parameters. |
| <P>The configuration object usually inherits from |
| <TT>org.apache.jmeter.config.AbstractConfigElement</TT>. It implements many of |
| the methods of <TT>org.apache.jmeter.gui.JMeterComponentModel</TT> that are |
| needed to effectively interact with JMeter. |
| </P> |
| <OL> |
| <LI><B>Constructor</B> - In the constructor you should at least define the |
| name of your configuration element. This is best delegated to the base class's |
| <TT>setName</TT> method. </LI> |
| <LI><B>Property Name Strings</B> - You should define a static final string for |
| each property you wish to define. These strings will serve as keys into a hash |
| table maintained by <TT>AbstractConfigElement</TT>. For example: <PRE> public static final HOST_NAME = "hostname";</PRE>would define a property |
| in the hash table for storing a host name. </LI> |
| <LI><B>Getters/Setters</B> - For each property name you define in the previous |
| step, define the appropriate accessor methods. The implementation of these |
| accessors should usually delegate to <TT>AbstractConfigElement</TT>. For |
| example: <PRE> public void setHostname(String hostname) |
| { setProperty(HOST_NAME, hostname); } |
| |
| public String getHostname() |
| { return (String)getProperty(HOST_NAME); } |
| </PRE>Some accessor implementations may be more complex. See the |
| <TT>UrlConfig</TT> object for a more involved example.</LI> |
| <LI><B><TT>String getClassLabel()</TT></B> - This is the label that will |
| display in the drop-down menu for adding your configuration element.</LI> |
| <LI><B><TT>clone()</TT></B> - Your configuration element is expected to be |
| cloneable.</LI> |
| <LI><B><TT>addConfigElement(ConfigElement)</TT></B> - A typical implementation |
| of this method looks like <PRE> public void addConfigElement(ConfigElement config) { |
| if (config instanceof MyConfig) |
| updatePropertyIfAbsent((MyConfig)config); |
| }</PRE>where <TT>updatePropertyIfAbsent</TT> is handled by the super class.</LI> |
| <LI><B><TT>getGuiClass</TT></B> - return the name of the this class's <A |
| href="#config-gui">corresponding GUI class</A>. |
| </LI></OL> |
| <P> |
| <H2><A name="config-gui">Configuration GUI</A></H2>Each configuration element you |
| define can have a companion GUI class. It helps to have a little knowledge of |
| Swing for this. Extend Swing's <TT>JPanel</TT> class and implement JMeter's |
| <TT>org.apache.jmeter.gui.ModelSupported</TT> interface. Remember that you can |
| review the <TT>UrlConfigGui</TT> example for hints if you get stuck. |
| </P> |
| <OL> |
| <LI><B>Data Members</B> - You should possess at least two data members: a |
| reference to your partner configuration element and a reference to a |
| <TT>org.apache.jmeter.gui.NamePanel</TT>. You will likely have several others |
| depending on how sophisticated your GUI is.</LI> |
| <LI><B>Add Panels</B> - The layout manager used for many of the panels used in |
| JMeter is <TT>org.apache.jmeter.gui.VerticalLayout</TT>. As the name implies, |
| it supports arranging other panels in a vertical fashion. You can define each |
| of your panels in a <TT>get</TT> method and add them to the configuration GUI |
| in a method called <B><TT>init</TT></B>. Once again, refer to |
| <TT>UrlConfigGui</TT> for an example.</LI> |
| <LI><B>Implement Listeners</B> - Implement listeners for your GUI components. |
| The <TT>UrlConfigGui</TT> serves as a satisfactory example.</LI> |
| <LI><B><TT>setModel</TT></B> - Use this method to have the model data member |
| set on your GUI instance. Run <TT>init</TT> from inside this method also.</LI> |
| <LI><B><TT>updateGui</TT></B> - Use this method to set the GUI fields from the |
| model.</LI></OL> |
| |
| <H2><A name="control">Generative Controller</A></H2>A generative controller is a |
| controller that generates an <TT>Entry</TT> object for use by a Sampler. |
| |
| <OL> |
| <LI><B><TT>createEntry</TT></B> - This method is the raison d'etre of the |
| <TT>org.apache.jmeter.control.SamplerController</TT> interface. The general |
| idea is to construct an <TT>Entry</TT> object and populate it with config |
| objects.</LI> |
| <LI><B><TT>clone</TT></B> - After you perform you cloning duties, be sure to |
| pass the cloned instance to the <TT>standardCloneProc</TT> method so that base |
| class cloning activities can complete.</LI> |
| <LI><B><TT>getClassLabel</TT></B> - This is the label displayed by the |
| drop-down menu for the controller.</LI> |
| <LI><B><TT>getGuiClass</TT></B> - This should return a Class object for the <A |
| href="#control-gui">associated GUI class</A>. </LI></OL> |
| <H2><A name="control-gui">Generative Controller GUI</A></H2>A generative |
| controller GUI class should extend <TT>JPanel</TT> and implement |
| <TT>ModelSupported</TT>. If your controller GUI doesn't involve anything beyond |
| the configuration GUI, you might be able to get away with inheriting from the |
| configuration gui class you created a couple steps ago. If you do this, you need |
| to at least override the <TT>setModel</TT> method to make sure that the correct |
| model is set on the class. You'll be passed a controller object but you'll want |
| to extract the config element from the controller to be used as the model for |
| your base class (the config gui). |
| <H2><A name="sampler">Sampler</A></H2>The sampler is responsible for actually |
| performing the work using the information provided in the configuration element. |
| The method of importance is <PRE>public SampleResult sample(Entry e)</PRE>It is here that you extract |
| configuration elements from the entry object you are passed. Then use these |
| configuration elements to perform the task you extension is suppose to do. |
| <H2><A name="installation">Installation</A></H2>Follow these steps to install your |
| extension. |
| |
| <OL> |
| <LI>Package the class files into a JAR file. </LI> |
| <LI>Place the JAR file into the <TT>ext</TT> subdirectory of the JMeter root |
| install directroy. </LI> |
| <LI>Edit the <TT>bin/jmeter.properties</TT> file of the JMeter installation. |
| Find the <TT>search_paths</TT> entry and add your JAR to the list. It should |
| look like <PRE>search_paths=ApacheJMeter.jar;classes;../ext/YourJar.jar</PRE></LI> |
| <LI>Run JMeter and watch the magic. </LI></OL> |
| |
| <H2><A name="tips">Tips</A></H2> |
| <OL> |
| <LI>You might consider using log4j as your logging utility since that's what |
| JMeter uses. It's helpful for figuring out what's going on. Not all JMeter |
| classes have been fully outfitted with logging statements. If things get |
| nasty, you might have to add your own to JMeter and recompile it to see what |
| is happening. |
| <P>If you do decide to use log4j and you set the priority (or level, as it |
| will soon be called) to debug, you will probably see way more than you need to |
| know. You can filter the JMeter stuff by making the following modifications to |
| <TT>log4j.conf</TT> in the JMeter's <TT>bin</TT> directory. The <B>bold</B> |
| text is added/modified <PRE> # Set the appenders for the categories |
| log4j.rootCategory=<B>info</B>,Root_Appender |
| <B>log4j.category.com.myfirm.jmeter=debug,</B> |
| log4j.category.org.apache.jmeter.control=debug |
| log4j.category.org.apache.jmeter.gui.tree.NonGuiTree=INFO,File_Appender |
| </PRE>Note that the root (default) debugging has been set to <B>info</B>. |
| This eliminates most log4j output from JMeter. The new line specifies the name |
| of the package containing JMeter extensions. (<TT>com.yourfirm.jmeter</TT>) in |
| this example. Note that it is not necessary to specify a particular class |
| name. Also, note that <B>no</B> appenders are specified - just the trailing |
| comma. If you specify Root_Appender here you'll see your message appear twice |
| (because you specified the same appender twice). All you really want to do is |
| override the priority.</P></LI> |
| <LI>Implement <TT>clone</TT> carefully. This is an often overlooked method for |
| a lot of folks. JMeter makes heavy use of cloning. Check out some of the |
| JMeter coniguration elements and controllers to see how they do it. Notice |
| that in most cases, a special method is usually invoked to perform base class |
| cloning activities. For configuration elements, this is |
| <TT>configureClone</TT>. For controllers, it is <TT>standardCloneProc</TT>. |
| </LI></OL> |
| <HR/> |
| </section> |
| </body> |
| </document> |