Hello,
    Here is the second part of the JavaSampler fix.  It builds on top of
the previous fix which allowed individual AbstractSampler subclasses to
decide whether to implement PerSampleClonable or PerThreadClonable.

    This second piece of the fix affects only the JavaSampler.  I've
implemented it a bit differently than I originally planned to -- I'm not
convinced that this is the most elegant solution, but it is relatively
simple and doesn't require changes to the base code, so I think its the
right thing to do for now.  In any case, it solves my problem.

    With these two fixes applied, the JavaSampler now behaves the way I
think it was intended to.  Each thread in the ThreadGroup will get a
single instance of the JavaSampler.  This JavaSampler will call
setupTest on its corresponding JavaSamplerClient to allow
initialization, and then it will call runTest for each iteration to
actually perform the sample.  When the run is complete it will call
teardownTest to allow the JavaSamplerClient to do any necessary cleanup
(e.g. closing a socket connection).

    While the new JavaSampler implementation has no API changes, it will
behave differently than the original implementation (which used a new
JavaSamplerClient for every sample, called setupTest and runTest on
every sample, and never called teardownTest), so it has the potential to
break existing tests.  I don't think there is any way to avoid this, and
it should be simple to fix the tests.

    Since there is the potential to break compatibility anyway, I'm
proposing a few minor modifications to the JavaSamplerClient API.  I'll
give details of these proposed changes in another email so that people
can discuss them before I submit the patch for those changes.

Jeremy
[EMAIL PROTECTED]
http://xirr.com/~jeremy_a

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.4
diff -u -r1.4 JavaSampler.java
--- 
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSampler.java
   30 Aug 2002 14:43:20 -0000      1.4
+++ 
jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/JavaSampler.java
   13 Mar 2003 16:01:18 -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
@@ -56,7 +56,9 @@
 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;
@@ -64,37 +66,73 @@
 import org.apache.jmeter.samplers.AbstractSampler;
 import org.apache.jmeter.samplers.Entry;
 import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.PerThreadClonable;
 import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.testelement.TestListener;
 import org.apache.log.Hierarchy;
 import org.apache.log.Logger;
 
-/**
- * 
- */
-
-
-public class JavaSampler extends AbstractSampler implements JavaSamplerClient {
 
-       /** Handle to Java client. **/
-       
-       public final static String CLASSNAME = "classname";
-       
-       public final static String ARGUMENTS = "arguments";
+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";
+
+    /**
+     * Property key representing the arguments for the JavaSamplerClient.
+     */
+    public final static String ARGUMENTS = "arguments";
+
+    /**
+     * The JavaSamplerClient instance used by this sampler to actually
+     * perform the sample.
+     */
        transient private JavaSamplerClient javaClient = null;
 
-       /** Logging  */
-       transient private static Logger log = 
Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
-
+    /**
+     * Logging
+     */
+    transient private static Logger log =
+        Hierarchy.getDefaultHierarchy().getLoggerFor("jmeter.protocol.java");
+
+    /**
+     * Set used to register all active JavaSamplers.  This is used so that
+     * the samplers can be notified when the test ends.
+     */
+    private static Set allSamplers = new HashSet();
+
+
+    /**
+     * Create a JavaSampler.
+     */
        public JavaSampler() {
                setArguments(new Arguments());
+        synchronized (allSamplers) {
+            allSamplers.add(this);
+        }
        }
        
+    /**
+     * Set the arguments (parameters) for the JavaSamplerClient to be
+     * executed with.
+     *
+     * @param args  the new arguments.  These replace any existing arguments.
+     */
        public void setArguments(Arguments args)
        {
                this.setProperty(ARGUMENTS,args);
        }
        
+    /**
+     * Get the arguments (parameters) for the JavaSamplerClient to be
+     * executed with.
+     *
+     * @return the arguments
+     */
        public Arguments getArguments()
        {
                return (Arguments)getProperty(ARGUMENTS);
@@ -111,7 +149,6 @@
        /**
         * Releases Java Client.
         */
-
        public void releaseJavaClient () {
                if (javaClient != null) {
                        
javaClient.teardownTest(createArgumentsHashMap(getArguments()));
@@ -151,12 +188,25 @@
         * 
         * @return test SampleResult
         */
-       
-
-       public SampleResult sample(Entry entry) {
-               return 
createJavaClient().runTest(createArgumentsHashMap(getArguments()));
-       }
-       
+    public SampleResult sample(Entry entry) {
+        if (javaClient == null) {
+            log.debug(whoAmI() + "Creating Java Client");
+            createJavaClient();
+            javaClient.setupTest(createArgumentsHashMap(getArguments()));
+        }
+        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();
@@ -170,7 +220,7 @@
                return newArgs;
        }
        
-               /**
+       /**
         * Returns reference to <code>JavaSamplerClient</code>.
         * 
         * The <code>createJavaClient()</code> method uses reflection
@@ -180,35 +230,24 @@
         * 
         * @return JavaSamplerClient reference.
         */
-
        public JavaSamplerClient createJavaClient() {
                if (javaClient == null) {
                        try {
                                Class javaClass = Class.forName(getClassname().trim(),
                                                
false,Thread.currentThread().getContextClassLoader());
-                               java.lang.reflect.Constructor[] constructors = 
javaClass.getConstructors();
-
-                               for (int i = 0; i < constructors.length; i++) {
-                                       Class[] params = 
constructors[i].getParameterTypes();
-                                       if (params.length == 0) {
-                                               Object[] args = {};
-                                               javaClient = 
(JavaSamplerClient)constructors[i].newInstance(args);
-                                               
javaClient.setupTest(createArgumentsHashMap(getArguments()));
-                                               if (log.isDebugEnabled()) {
-                                                       log.debug(whoAmI() + 
"\tCreated:\t"+ getClassname()+ "@" + Integer.toHexString(javaClient.hashCode()));
-                                               }
-                                               break;
-                                       }
-                               }
+                javaClient = (JavaSamplerClient)javaClass.newInstance();
 
+                if (log.isDebugEnabled()) {
+                    log.debug(whoAmI() + "\tCreated:\t" + getClassname() +
+                            "@" + Integer.toHexString(javaClient.hashCode()));
+                }
                        } catch (Exception e) {
-                               log.error(whoAmI() + "\tException creating: " + 
getClassname(),e);
+                               log.error(whoAmI() + "\tException creating: " +
+                                               getClassname(),e);
                                javaClient = this;
                        }
                }
-               
                return javaClient;
-                       
        }
        
        /**
@@ -219,7 +258,6 @@
         * 
         * @return reference to JavaSamplerClient
         */
-       
        public JavaSamplerClient retrieveJavaClient() {
                return javaClient;
        }
@@ -251,7 +289,8 @@
                SampleResult results = new SampleResult();
                results.setTime(0);
                results.setSuccessful(false);
-               results.setResponseData(new String("Class not found: " + 
getClassname()).getBytes());
+               results.setResponseData(new String("Class not found: " +
+                                       getClassname()).getBytes());
                results.setSampleLabel("ERROR: " + getClassname());
                return results;
        }
@@ -264,4 +303,37 @@
                return sb.toString();
        }
 
-}
\ No newline at end of file
+
+    // TestListener implementation
+
+    public void testStarted() {
+        log.debug(whoAmI() + "\ttestStarted");
+    }
+
+    public void testStarted(String host) {
+        log.debug(whoAmI() + "\ttestStarted(" + host + ")");
+    }
+
+    /**
+     * 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.
+     */
+    public void testEnded() {
+        log.debug(whoAmI() + "\ttestEnded");
+        synchronized (allSamplers) {
+            Iterator i = allSamplers.iterator();
+            while (i.hasNext()) {
+                JavaSampler sampler = (JavaSampler)i.next();
+                sampler.releaseJavaClient();
+                i.remove();
+            }
+        }
+    }
+
+    public void testEnded(String host) {
+        testEnded();
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to