In my recent work with the JavaSampler I have noticed a couple of minor shortcomings in the API. I would like to fix these shortcomings, but this will require changes to the JavaSamplerClient interface, which will in turn require modifications to any tests that use the JavaSampler. I believe this will be an easy migration, and I've tried to define the changes in a way that will make it possible to make future changes without breaking existing code again.
However, since this will break any existing implementations of JavaSamplerClient, I want to make sure that people have a chance to discuss/object before the changes are committed. So if you don't agree with these changes, please speak up in the next couple days. If I don't hear anything, I'll ask the committers to go ahead with the change. I think now is the best time to make these changes, because the recent fixes to JavaSampler have changed the behavior somewhat, so some tests may need to be modified anyway.
Take a look at the old and new implementation of the SleepTest. I think you will see that the differences aren't extensive (it should be an easy migration), but that the new implementation is a bit simpler, mostly because of some new convenience methods. Along with the previous two changes I've submitted for the JavaSampler, this new implementation should also be more efficient.
Here is a list of the changes I have made. I haven't gone into great detail about the reasons for the changes -- let me know if it's not readily apparent.
1) I've added a method to JavaSamplerClient called getDefaultParameters. This returns an Arguments instance with the names and default values of parameters. This allows the client to specify which parameters it accepts. The JavaConfigGui has been modified to get this list of parameters and populate the arguments table with this information. This means the user doesn't have to remember the names of the parameters, and they can see the default values that will be used if they don't specify new values.
The GUI will continue to allow the user to specify additional parameters. And in fact, if a JavaSamplerClient returns an empty list or null for the default parameters then it will continue to work just as it does today. This makes migration very simple -- just add the method declaration and return null. But clients which actually return an argument list will be easier for people to use.
2) A HashMap of arguments (parameters) is passed in to every call of setupTest, runTest, and teardownTest. I don't like this for a couple of reasons:
a) it should probably be a Map rather than a HashMap
b) the HashMap currently gets recreated for every call, which I would like to avoid. Changing it to keep a single instance across all calls for a test would technically be changing the API, since currently a test could modify the contents without affecting future calls. Although I doubt that this change would actually affect any existing tests.
c) passing the HashMap in to runTest might encourage a JavaSamplerClient implementation to retrieve the parameters from the HashMap in every call to runTest, while I would think it would be best to get the parameters once in setupTest and then save them off somewhere for all of the runTest iterations.
However, since I'm requring minor code changes anyway, I would like to change the parameter from a HashMap to a new JavaSamplerContext class. Currently this is just a wrapper around the parameters, with some convenience methods to simplify tests. This wrapper also forces the arguments to be used read-only. This new implementation doesn't force clients to get the parameters only during setupTest, but it does encourage this through the naming and the JavaDoc.
I also hope that this would help avoid further changes to JavaSamplerClient in the future -- if we decide we need to give more data to the client, this data could be added to JavaSamplerContext and existing tests would continue to work without modification.
Migration to these new method signatures is quite simple -- change the parameter from a HashMap to a JavaSamplerContext, and use the getParameter( ) method to get the value of a parameter as a String (instead of using HashMap.get( )). There are additional methods for getting the parameter as an integer or long value (others can be added if needed). This can simplify the client code since it doesn't have to be responsible for doing the parsing and exception handling.
3) I've changed JavaSampler to not implement JavaSamplerClient. The setupTest, runTest, and teardownTest methods in JavaSampler have been removed. The current error-handling semantics (which these methods were used for) are now implemented through an inner class. The main reason for this change is to reduce confusion over which class/interface should be used when implementing a Java test. Documentation updates should also help with this. (I'll do the documentation updates if this patch is committed.) This shouldn't affect any existing tests, unless they previously (incorrectly) extended JavaSampler instead of implementing JavaSamplerClient.
4) I've created an AbstractJavaSamplerClient which implements JavaSamplerClient and provides default implementations of all methods besides runTest( ). This may simplify development of Java tests somewhat, but my main reason for adding this class is an attempt to protect JavaSamplerClient implementations from any future changes. As I claim in the JavaDoc for these classes, it might be necessary at some point to add methods to JavaSamplerClient, requiring code changes from all implementations. But we could add default implementations for any new methods to AbstractJavaSamplerClient. Therefore, a test which extended AbstractJavaSamplerClient instead of implementing JavaSamplerClient directly would be protected from these changes and shouldn't need to be updated.
I think that's about it. As always, let me know if there are any questions.
Jeremy [EMAIL PROTECTED] http://xirr.com/~jeremy_a/
Index:
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/test/SleepTest.java
===================================================================
RCS file:
/home/cvspublic/jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/test/SleepTest.java,v
retrieving revision 1.4
diff -u -r1.4 SleepTest.java
---
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/test/SleepTest.java
30 Aug 2002 14:43:21 -0000 1.4
+++
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/test/SleepTest.java
16 Mar 2003 21:14:23 -0000
@@ -2,7 +2,7 @@
* ====================================================================
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * Copyright (c) 2001,2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,123 +56,192 @@
package org.apache.jmeter.protocol.java.test;
import java.io.Serializable;
-import java.util.HashMap;
import java.util.Iterator;
-import java.util.Map.Entry;
-import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
+import org.apache.jmeter.config.Arguments;
+import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
+import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
-import org.apache.log.Hierarchy;
-import org.apache.log.Logger;
/**
* The <code>SleepTest</code> class is a simple example class for a
* JMeter Java protocol client. The class implements the
* <code>JavaSamplerClient</code> interface.
+ * <p>
+ * During each sample, this client will sleep for some amount of
+ * time. The amount of time to sleep is determined from the
+ * two parameters SleepTime and SleepMask using the formula:
+ * <pre>
+ * totalSleepTime = SleepTime + (System.currentTimeMillis() % SleepMask)
+ * </pre>
+ * Thus, the SleepMask provides a way to add a random component
+ * to the sleep time.
*/
-
-public class SleepTest implements JavaSamplerClient,Serializable {
- /** Define category for logging */
- transient private static Logger log =
Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
- /** */
- private long sleepTime = 1000;
- /** */
- private long sleepMask = 0x3ff;
- /**
- * Default constructor for <code>SleepTest</code>.
- *
- * [EMAIL PROTECTED] org.apache.jmeter.protocol.java.config.JavaConfig
JavaConfig}
- * uses the default constructor to instantiate an instance of
- * the client class.
- */
+public class SleepTest extends AbstractJavaSamplerClient
+ implements Serializable {
+ /**
+ * The default value of the SleepTime parameter, in milliseconds.
+ */
+ public static final long DEFAULT_SLEEP_TIME = 1000;
+
+ /**
+ * The default value of the SleepMask parameter.
+ */
+ public static final long DEFAULT_SLEEP_MASK = 0x3ff;
+
+ /**
+ * The base number of milliseconds to sleep during each sample.
+ */
+ private long sleepTime;
+
+ /**
+ * A mask to be applied to the current time in order to add a
+ * random component to the sleep time.
+ */
+ private long sleepMask;
+
+ /**
+ * Default constructor for <code>SleepTest</code>.
+ *
+ * The Java Sampler uses the default constructor to instantiate
+ * an instance of the client class.
+ */
public SleepTest() {
- log.debug(whoAmI() + "\tConstruct");
+ getLogger().debug(whoAmI() + "\tConstruct");
}
- /**
- * @see JavaSamplerClient#setupTest()
- *
- * setupTest() provides a way to do any initialization that may be required.
- */
- public void setupTest(HashMap arguments) {
- log.debug(whoAmI() + "\tsetupTest()");
- Iterator argsIt = arguments.entrySet().iterator();
- while (argsIt.hasNext()) {
- Entry entry = (Entry)argsIt.next();
- log.debug(entry.getKey().toString() + "=" +
entry.getValue().toString());
- }
-
- if (arguments.containsKey("SleepTime")) {
- setSleepTime(arguments.get("SleepTime"));
- }
-
- if (arguments.containsKey("SleepMask")) {
- setSleepMask(arguments.get("SleepMask"));
- }
- }
-
- /**
- * @see JavaSamplerClient#teardownTest()
- *
- * teardownTest() provides a way to do any clean-up that may be required.
- */
- public void teardownTest(HashMap arguments) {
- log.debug(whoAmI() + "\tteardownTest()");
- Iterator argsIt = arguments.entrySet().iterator();
- while (argsIt.hasNext()) {
- Entry entry = (Entry)argsIt.next();
- log.debug(entry.getKey().toString() + "=" +
entry.getValue().toString());
- }
- }
-
- /**
- * @see JavaSamplerClient#runTest()
- *
- * runTest() is called for each sample. The method returns a
- * <code>SampleResult</code> object. The method must calculate
- * how long the sample took to execute.
- */
- public SampleResult runTest(HashMap arguments) {
-
+ /**
+ * Do any initialization required by this client. In this case,
+ * initialization consists of getting the values of the SleepTime
+ * and SleepMask parameters. It is generally recommended to do
+ * any initialization such as getting parameter values in the
+ * setupTest method rather than the runTest method in order to
+ * add as little overhead as possible to the test.
+ *
+ * @param context the context to run with. This provides access
+ * to initialization parameters.
+ */
+ public void setupTest(JavaSamplerContext context) {
+ getLogger().debug(whoAmI() + "\tsetupTest()");
+ listParameters(context);
+
+ sleepTime = context.getLongParameter("SleepTime", 1000);
+ sleepMask = context.getLongParameter("SleepMask", 0x3ff);
+ }
+
+ /**
+ * Perform a single sample. In this case, this method will
+ * simply sleep for some amount of time.
+ * <p>
+ * This method returns a <code>SampleResult</code> object.
+ * <code>SampleResult</code> has many fields which can be
+ * used. At a minimum, the test should use
+ * <code>SampleResult.setTime</code> to set the time that
+ * the test required to execute. It is also a good idea to
+ * set the sampleLabel and the successful flag.
+ *
+ * @see org.apache.jmeter.samplers.SampleResult.setTime(long)
+ * @see org.apache.jmeter.samplers.SampleResult.setSuccessful(boolean)
+ * @see org.apache.jmeter.samplers.SampleResult.setSampleLabel(java.lang.String)
+ *
+ * @param context the context to run with. This provides access
+ * to initialization parameters.
+ *
+ * @return a SampleResult giving the results of this
+ * sample.
+ */
+ public SampleResult runTest(JavaSamplerContext context) {
SampleResult results = new SampleResult();
+
try {
- //
- // Generate a random value using the current time.
- //
- long ct = System.currentTimeMillis();
- ct %= getSleepMask();
- //
// Record sample start time.
- //
long start = System.currentTimeMillis();
- //
+
+ // Generate a random value using the current time.
+ long ct = start % getSleepMask();
+
// Execute the sample. In this case sleep for the
// specified time.
- //
Thread.sleep(getSleepTime() + ct);
- //
+
// Record end time and populate the results.
- //
long end = System.currentTimeMillis();
+
results.setTime(end - start);
results.setSuccessful(true);
- results.setSampleLabel("Sleep Test: time = "+getSleepTime() +
ct);
+ results.setSampleLabel("Sleep Test: time = " +
+ (getSleepTime() + ct));
} catch (Exception e) {
+ getLogger().error("SleepTest: error during sample", e);
+ results.setSuccessful(false);
}
- if (log.isDebugEnabled()) {
- log.debug(whoAmI() + "\trunTest()" + "\tTime:\t" +
results.getTime());
- Iterator argsIt = arguments.entrySet().iterator();
- while (argsIt.hasNext()) {
- Entry entry = (Entry)argsIt.next();
- log.debug(entry.getKey().toString() + "=" +
entry.getValue().toString());
- }
- }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(whoAmI() + "\trunTest()" + "\tTime:\t" +
results.getTime());
+ listParameters(context);
+ }
return results;
+ }
+ /**
+ * Do any clean-up required by this test. In this case no
+ * clean-up is necessary, but some messages are logged for
+ * debugging purposes.
+ *
+ * @param context the context to run with. This provides access
+ * to initialization parameters.
+ */
+ public void teardownTest(JavaSamplerContext context) {
+ getLogger().debug(whoAmI() + "\tteardownTest()");
+ listParameters(context);
}
+ /**
+ * Provide a list of parameters which this test supports. Any
+ * parameter names and associated values returned by this method
+ * will appear in the GUI by default so the user doesn't have
+ * to remember the exact names. The user can add other parameters
+ * which are not listed here. If this method returns null then
+ * no parameters will be listed. If the value for some parameter
+ * is null then that parameter will be listed in the GUI with
+ * an empty value.
+ *
+ * @return a specification of the parameters used by this
+ * test which should be listed in the GUI, or null
+ * if no parameters should be listed.
+ */
+ public Arguments getDefaultParameters() {
+ Arguments params = new Arguments();
+ params.addArgument("SleepTime", String.valueOf(DEFAULT_SLEEP_TIME));
+ params.addArgument("SleepMask", "0x" +
+ (Long.toHexString(DEFAULT_SLEEP_MASK)).toUpperCase());
+ return params;
+ }
+
+ /**
+ * Dump a list of the parameters in this context to the debug
+ * log.
+ *
+ * @param context the context which contains the initialization
+ * parameters.
+ */
+ private void listParameters(JavaSamplerContext context) {
+ if (getLogger().isDebugEnabled()) {
+ Iterator argsIt = context.getParameterNamesIterator();
+ while (argsIt.hasNext()) {
+ String name = (String)argsIt.next();
+ getLogger().debug(name + "=" + context.getParameter(name));
+ }
+ }
+ }
+
+ /**
+ * Generate a String identifier of this test for debugging
+ * purposes.
+ *
+ * @return a String identifier for this test instance
+ */
private String whoAmI() {
StringBuffer sb = new StringBuffer();
sb.append(Thread.currentThread().toString());
@@ -181,22 +250,23 @@
return sb.toString();
}
- private long getSleepTime() {return sleepTime;}
- private long getSleepMask() {return sleepMask;}
- private void setSleepTime(Object arg) {
- try {
- sleepTime = Long.parseLong((String)arg);
- } catch (Exception e) {
- log.debug("Exception getting sleepTime:\t",e);
- sleepTime = 1000l;
- }
- }
- private void setSleepMask(Object arg) {
- try {
- sleepMask = Long.parseLong((String)arg);
- } catch (Exception e) {
- log.debug("Exception getting sleepMask:\t",e);
- sleepMask = 0x3ff;
- }
- }
-}
\ No newline at end of file
+ /**
+ * Get the value of the sleepTime field.
+ *
+ * @return the base number of milliseconds to sleep during
+ * each sample.
+ */
+ private long getSleepTime() {
+ return sleepTime;
+ }
+
+ /**
+ * Get the value of the sleepMask field.
+ *
+ * @return a mask to be applied to the current time in order
+ * to add a random component to the sleep time.
+ */
+ private long getSleepMask() {
+ return sleepMask;
+ }
+}
Index:
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/config/gui/JavaConfigGui.java
===================================================================
RCS file:
/home/cvspublic/jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/config/gui/JavaConfigGui.java,v
retrieving revision 1.6
diff -u -r1.6 JavaConfigGui.java
---
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/config/gui/JavaConfigGui.java
28 Feb 2003 14:21:51 -0000 1.6
+++
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/config/gui/JavaConfigGui.java
16 Mar 2003 21:34:22 -0000
@@ -2,7 +2,7 @@
* ====================================================================
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2002,2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,11 @@
package org.apache.jmeter.protocol.java.config.gui;
import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
@@ -64,6 +68,7 @@
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
+import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.AbstractConfigGui;
import org.apache.jmeter.config.gui.ArgumentsPanel;
@@ -72,10 +77,10 @@
import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
-import org.apache.log.Hierarchy;
-import org.apache.log.Logger;
import org.apache.jorphan.gui.layout.VerticalLayout;
import org.apache.jorphan.reflect.ClassFinder;
+import org.apache.log.Hierarchy;
+import org.apache.log.Logger;
/**
@@ -85,9 +90,9 @@
* @version $Revision: 1.6 $
*/
-public class JavaConfigGui extends AbstractConfigGui
-{
- transient private static Logger log =
Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
+public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
+ transient private static Logger log =
+ Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
private static String CLASSNAMECOMBO = "classnamecombo";
private JComboBox classnameCombo;
@@ -169,13 +174,14 @@
// Remove the JavaConfig class from the list since it only
implements the interface for
// error conditions.
-
possibleClasses.remove("org.apache.jmeter.protocol.java.sampler.JavaSampler");
+
possibleClasses.remove("org.apache.jmeter.protocol.java.sampler.JavaSampler$ErrorSamplerClient");
} catch (Exception e) {
log.debug("Exception getting interfaces.",e);
}
classnameCombo = new JComboBox(possibleClasses.toArray());
+ classnameCombo.addActionListener(this);
classnameCombo.setName(CLASSNAMECOMBO);
classnameCombo.setEditable(false);
panel.add(classnameCombo);
@@ -183,6 +189,51 @@
return panel;
}
+
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource() == classnameCombo) {
+ String className = (String)classnameCombo.getSelectedItem();
+ try {
+ JavaSamplerClient client = (JavaSamplerClient)Class.forName(
+ className.trim(),
+ true,
+ Thread.currentThread().getContextClassLoader()
+ ).newInstance();
+
+ Arguments currArgs = new Arguments();
+ argsPanel.modifyTestElement(currArgs);
+ Map currArgsMap = currArgs.getArgumentsAsMap();
+
+ Arguments newArgs = new Arguments();
+ Arguments testParams = client.getDefaultParameters();
+ if (testParams != null) {
+ Iterator i = testParams.getArguments().iterator();
+ while (i.hasNext()) {
+ Argument arg = (Argument)i.next();
+ String name = arg.getName();
+ Object value = arg.getValue();
+
+ // If a user has set parameters in one test, and then
+ // selects a different test which supports the same
+ // parameters, those parameters should have the same
+ // values that they did in the original test.
+ if (currArgsMap.containsKey(name)) {
+ Object newVal = currArgsMap.get(name);
+ if (newVal != null &&
+ newVal.toString().length() > 0) {
+ value = newVal;
+ }
+ }
+ newArgs.addArgument(name, value);
+ }
+ }
+
+ argsPanel.configure(newArgs);
+ } catch (Exception e) {
+ log.error("Error getting argument list for " + className, e);
+ }
+ }
+ }
protected JPanel getParameterPanel()
{
Index:
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSamplerClient.java
===================================================================
RCS file:
/home/cvspublic/jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSamplerClient.java,v
retrieving revision 1.1
diff -u -r1.1 JavaSamplerClient.java
---
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSamplerClient.java
11 Aug 2002 19:24:53 -0000 1.1
+++
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSamplerClient.java
16 Mar 2003 21:38:43 -0000
@@ -2,7 +2,7 @@
* ====================================================================
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2002,2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,41 +54,111 @@
*/
package org.apache.jmeter.protocol.java.sampler;
-import java.util.HashMap;
-
+import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.samplers.SampleResult;
+
/**
- *<code>JavaSamplerClient</code> provides a standard
- * interface to execute external Java programs within JMeter.
+ * This interface defines the interactions between the JavaSampler
+ * and external Java programs which can be executed by JMeter. Any
+ * Java class which wants to be executed as a JMeter test must
+ * implement this interface (either directly or indirectly through
+ * AbstractJavaSamplerClient).
+ * <p>
+ * JMeter will create one instance of a JavaSamplerClient implementation
+ * for each user/thread in the test. Additional instances may be
+ * created for internal use by JMeter (for example, to find out
+ * what parameters are supported by the client).
+ * <p>
+ * When the test is started, setupTest() will be called on each
+ * thread's JavaSamplerClient instance to initialize the client.
+ * Then runTest() will be called for each iteration of the test.
+ * Finally, teardownTest() will be called to allow the client
+ * to do any necessary clean-up.
+ * <p>
+ * The JMeter JavaSampler GUI allows a list of parameters to be
+ * defined for the test. These are passed to the various test
+ * methods through the JavaSamplerContext. A list of default
+ * parameters can be defined through the getDefaultParameters()
+ * method. These parameters and any default values associated
+ * with them will be shown in the GUI. Users can add other
+ * parameters as well.
+ * <p>
+ * While it may be necessary to make changes to the JavaSamplerClient
+ * interface from time to time (therefore requiring changes to any
+ * implementations of this interface), we intend to make this abstract
+ * class provide reasonable implementations of any new methods so that
+ * subclasses do not necessarily need to be updated for new versions.
+ * Therefore, when creating a new JavaSamplerClient implementation,
+ * developers are encouraged to subclass this abstract class rather
+ * than implementing the JavaSamplerClient interface directly.
+ * Implementing JavaSamplerClient directly will continue to be
+ * supported for cases where extending this class is not possible
+ * (for example, when the client class is already a subclass of some
+ * other class).
+ *
+ * @see JavaSamplerContext
*
* @author Brad Kiewel
+ * @author Jeremy Arnold
* @version $Revision: 1.1 $
*/
public interface JavaSamplerClient {
-
- /**
- * Setup any resources need for each test run.
- */
-
- public void setupTest(HashMap arguments);
-
- /**
- * Perform any clean up at the end of a test run.
- */
-
- public void teardownTest(HashMap arguments);
-
- /**
- * Performs test for each iteration.
- *
- * The <code>runTest()</code> method performs one test interation
- * each time it is called. The method returns a SampleResult object.
- * The method should, has a minimum, place the response time in
- * the SampleResult object.
- *
- * @return SampleResult object with results of the test run.
- */
- public SampleResult runTest(HashMap arguments);
-}
\ No newline at end of file
+ /**
+ * Do any initialization required by this client. It is
+ * generally recommended to do any initialization such as
+ * getting parameter values in the setupTest method rather
+ * than the runTest method in order to add as little overhead
+ * as possible to the test.
+ *
+ * @param context the context to run with. This provides access
+ * to initialization parameters.
+ */
+ public void setupTest(JavaSamplerContext context);
+
+ /**
+ * Perform a single sample for each iteration. This method
+ * returns a <code>SampleResult</code> object.
+ * <code>SampleResult</code> has many fields which can be
+ * used. At a minimum, the test should use
+ * <code>SampleResult.setTime</code> to set the time that
+ * the test required to execute. It is also a good idea to
+ * set the sampleLabel and the successful flag.
+ *
+ * @see org.apache.jmeter.samplers.SampleResult.setTime(long)
+ * @see org.apache.jmeter.samplers.SampleResult.setSuccessful(boolean)
+ * @see org.apache.jmeter.samplers.SampleResult.setSampleLabel(java.lang.String)
+ *
+ * @param context the context to run with. This provides access
+ * to initialization parameters.
+ *
+ * @return a SampleResult giving the results of this
+ * sample.
+ */
+ public SampleResult runTest(JavaSamplerContext context);
+
+ /**
+ * Do any clean-up required by this test at the end of a test run.
+ *
+ * @param context the context to run with. This provides access
+ * to initialization parameters.
+ */
+ public void teardownTest(JavaSamplerContext context);
+
+ /**
+ * Provide a list of parameters which this test supports. Any
+ * parameter names and associated values returned by this method
+ * will appear in the GUI by default so the user doesn't have
+ * to remember the exact names. The user can add other parameters
+ * which are not listed here. If this method returns null then
+ * no parameters will be listed. If the value for some parameter
+ * is null then that parameter will be listed in the GUI with
+ * an empty value.
+ *
+ * @return a specification of the parameters used by this
+ * test which should be listed in the GUI, or null
+ * if no parameters should be listed.
+ */
+ public Arguments getDefaultParameters();
+}
Index:
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSampler.java
===================================================================
RCS file:
/home/cvspublic/jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSampler.java,v
retrieving revision 1.6
diff -u -r1.6 JavaSampler.java
---
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSampler.java
15 Mar 2003 14:44:52 -0000 1.6
+++
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSampler.java
16 Mar 2003 22:12:24 -0000
@@ -55,12 +55,10 @@
package org.apache.jmeter.protocol.java.sampler;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
-import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.config.JavaConfig;
import org.apache.jmeter.samplers.AbstractSampler;
@@ -72,17 +70,19 @@
import org.apache.log.Hierarchy;
import org.apache.log.Logger;
-public class JavaSampler extends AbstractSampler implements JavaSamplerClient,
PerThreadClonable, TestListener
-{
- /**
- * Property key representing the classname of the JavaSamplerClient to use.
- */
- public final static String CLASSNAME = "classname";
+public class JavaSampler extends AbstractSampler
+ implements PerThreadClonable, TestListener {
/**
- * Property key representing the arguments for the JavaSamplerClient.
- */
+ * Property key representing the classname of the JavaSamplerClient to
+ * user.
+ */
+ public final static String CLASSNAME = "classname";
+
+ /**
+ * Property key representing the arguments for the JavaSamplerClient.
+ */
public final static String ARGUMENTS = "arguments";
/**
@@ -90,11 +90,19 @@
* the sample.
*/
transient private JavaSamplerClient javaClient = null;
+
+ /**
+ * The JavaSamplerContext instance used by this sampler to hold
+ * information related to the test run, such as the parameters
+ * specified for the sampler client.
+ */
+ transient private JavaSamplerContext context = null;
/**
* Logging
*/
- transient private static Logger log =
Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
+ transient private static Logger log =
+ Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
/**
* Set used to register all active JavaSamplers. This is used so that the
@@ -147,19 +155,19 @@
/**
* Releases Java Client.
*/
- public void releaseJavaClient()
- {
+ private void releaseJavaClient () {
if (javaClient != null)
{
- javaClient.teardownTest(createArgumentsHashMap(getArguments()));
+ javaClient.teardownTest(context);
}
javaClient = null;
+ context = null;
}
/**
- * Sets the Classname attribute of the JavaConfig object
+ * Sets the Classname attribute of the JavaConfig object
*
- [EMAIL PROTECTED] classname The new Classname value
+ * @param classname the new Classname value
*/
public void setClassname(String classname)
{
@@ -167,9 +175,9 @@
}
/**
- * Gets the Classname attribute of the JavaConfig object
+ * Gets the Classname attribute of the JavaConfig object
*
- [EMAIL PROTECTED] The Classname value
+ * @return the Classname value
*/
public String getClassname()
{
@@ -181,8 +189,9 @@
*
* The <code>sample()</code> method retrieves the reference to the
* Java client and calls its <code>runTest()</code> method.
- * @see Sampler#sample()
- * @see JavaSamplerClient#runTest()
+ *
+ * @see Sampler#sample(org.apache.jmeter.samplers.Entry)
+ * @see JavaSamplerClient#runTest(JavaSamplerContext)
*
* @return test SampleResult
*/
@@ -192,32 +201,10 @@
{
log.debug(whoAmI() + "Creating Java Client");
createJavaClient();
- javaClient.setupTest(createArgumentsHashMap(getArguments()));
+ javaClient.setupTest(context);
}
- return javaClient.runTest(createArgumentsHashMap(getArguments()));
- }
- /**
- * Convert the arguments parameter into a HashMap which can be passed
- * to the JavaSamplerClient. The "name" of each Argument
- * in args is added to the HashMap as a key, and the "value"
- * is the value associated with that key. The original Arguments are
- * not modified.
- *
- * @param args the Arguments to convert to a HashMap
- * @return a HashMap representation of the Arguments
- */
- public HashMap createArgumentsHashMap(Arguments args)
- {
- HashMap newArgs = new HashMap();
- Iterator iter = args.iterator();
- while (iter.hasNext())
- {
- Argument item = (Argument) iter.next();
- newArgs.put(item.getName(), item.getValue());
- }
-
- return newArgs;
+ return createJavaClient().runTest(context);
}
/**
@@ -230,24 +217,27 @@
*
* @return JavaSamplerClient reference.
*/
- public JavaSamplerClient createJavaClient()
- {
+ private JavaSamplerClient createJavaClient() {
if (javaClient == null)
{
try
{
- Class javaClass = Class.forName(getClassname().trim(), false,
Thread.currentThread().getContextClassLoader());
+ Class javaClass = Class.forName(getClassname().trim(),
+ false,
+ Thread.currentThread().getContextClassLoader());
javaClient = (JavaSamplerClient) javaClass.newInstance();
+ context = new JavaSamplerContext(getArguments());
- if (log.isDebugEnabled())
- {
- log.debug(whoAmI() + "\tCreated:\t" + getClassname() + "@" +
Integer.toHexString(javaClient.hashCode()));
+ if (log.isDebugEnabled()) {
+ log.debug(whoAmI() + "\tCreated:\t" + getClassname() +
+ "@" + Integer.toHexString(javaClient.hashCode()));
}
}
catch (Exception e)
{
- log.error(whoAmI() + "\tException creating: " + getClassname(), e);
- javaClient = this;
+ log.error(whoAmI() + "\tException creating: " +
+ getClassname(), e);
+ javaClient = new ErrorSamplerClient();
}
}
return javaClient;
@@ -261,46 +251,16 @@
*
* @return reference to JavaSamplerClient
*/
- public JavaSamplerClient retrieveJavaClient()
- {
+ private JavaSamplerClient retrieveJavaClient() {
return javaClient;
}
/**
- * Provide default setupTest() implementation for error conditions.
- * @see JavaSamplerClient#setupTest()
- */
- public void setupTest(HashMap arguments)
- {
- log.debug(whoAmI() + "\tsetupTest");
- }
-
- /**
- * Provide default teardownTest() implementation for error conditions.
- * @see JavaSamplerClient#teardownTest()
- */
- public void teardownTest(HashMap arguments)
- {
- log.debug(whoAmI() + "\tteardownTest");
- javaClient = null;
- }
-
- /**
- * Return SampleResult with data on error.
- * @see JavaSamplerClient#runTest()
+ * Generate a String identifier of this instance for debugging
+ * purposes.
+ *
+ * @return a String identifier for this sampler instance
*/
- public SampleResult runTest(HashMap arguments)
- {
- log.debug(whoAmI() + "\trunTest");
- Thread.yield();
- SampleResult results = new SampleResult();
- results.setTime(0);
- results.setSuccessful(false);
- results.setResponseData(new String("Class not found: " +
getClassname()).getBytes());
- results.setSampleLabel("ERROR: " + getClassname());
- return results;
- }
-
private String whoAmI()
{
StringBuffer sb = new StringBuffer();
@@ -323,8 +283,8 @@
}
/**
- * Method called at the end of the test. This is called only on one
- * instance of JavaSampler. This method will loop throuh all of the
+ * Method called at the end of the test. This is called only on one
+ * instance of JavaSampler. This method will loop through all of the
* other JavaSamplers which have been registered (automatically in the
* constructor) and notify them that the test has ended, allowing the
* JavaSamplerClients to cleanup.
@@ -349,4 +309,21 @@
testEnded();
}
+ class ErrorSamplerClient extends AbstractJavaSamplerClient {
+ /**
+ * Return SampleResult with data on error.
+ * @see JavaSamplerClient#runTest()
+ */
+ public SampleResult runTest(JavaSamplerContext context) {
+ log.debug(whoAmI() + "\trunTest");
+ Thread.yield();
+ SampleResult results = new SampleResult();
+ results.setTime(0);
+ results.setSuccessful(false);
+ results.setResponseData(new String("Class not found: " +
+ getClassname()).getBytes());
+ results.setSampleLabel("ERROR: " + getClassname());
+ return results;
+ }
+ }
}
JavaSampler2b.zip
Description: Zip compressed data
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
