Author: pmouawad
Date: Tue Nov 28 21:06:45 2017
New Revision: 1816573

URL: http://svn.apache.org/viewvc?rev=1816573&view=rev
Log:
Bug 61829 - JMS Point-to-Point : If Receive Queue is empty and a timeout is 
set, it is not taken into account
Fixes also timeout == 0 is reset to 2s
Bugzilla Id: 61829

Added:
    
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java
   (with props)
Modified:
    jmeter/trunk/bin/testfiles/JMS_TESTS.csv
    jmeter/trunk/bin/testfiles/JMS_TESTS.jmx
    jmeter/trunk/bin/testfiles/JMS_TESTS.xml
    
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/FixedQueueExecutor.java
    
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/JMSSampler.java
    
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/QueueExecutor.java
    
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TemporaryQueueExecutor.java
    jmeter/trunk/xdocs/changes.xml

Modified: jmeter/trunk/bin/testfiles/JMS_TESTS.csv
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/bin/testfiles/JMS_TESTS.csv?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- jmeter/trunk/bin/testfiles/JMS_TESTS.csv (original)
+++ jmeter/trunk/bin/testfiles/JMS_TESTS.csv Tue Nov 28 21:06:45 2017
@@ -14,6 +14,7 @@ JMS-P2P-Read,200,1 message(s) received s
 JMS-P2P-RequestOnlyForClear,200,OK,TG-JMS-P2P 1-1,text,true,1,1,1,0
 JMS-P2P-Clear,200,1 message(s) removed using receive timeout:100ms,TG-JMS-P2P 
1-1,text,true,1,1,1,0
 JMS-P2P-BrowseAfterClear,200,0 messages available on the queue,TG-JMS-P2P 
1-1,text,true,1,1,1,0
+JMS-P2P-Timeout,,No reply message received,TG-JMS-P2P 1-1,text,true,1,1,1,0
 JMS Publisher-NonDurable,200,1 messages published,TG-JMS-PS 2-1,,true,1,1,1,0
 JMS Subscriber-NonDurable,200,1 message(s) received successfully of 1 
expected,TG-JMS-PS 2-1,text,true,1,1,1,0
 JMS Publisher-Persistent,200,1 messages published,TG-JMS-PS-Selector-receive 
3-1,,true,1,1,1,0

Modified: jmeter/trunk/bin/testfiles/JMS_TESTS.jmx
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/bin/testfiles/JMS_TESTS.jmx?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- jmeter/trunk/bin/testfiles/JMS_TESTS.jmx (original)
+++ jmeter/trunk/bin/testfiles/JMS_TESTS.jmx Tue Nov 28 21:06:45 2017
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<jmeterTestPlan version="1.2" properties="3.4" jmeter="3.4-SNAPSHOT.20171119">
+<jmeterTestPlan version="1.2" properties="3.4" jmeter="4.0-SNAPSHOT.20171128">
   <hashTree>
     <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" 
enabled="true">
       <stringProp name="TestPlan.comments"></stringProp>
@@ -663,6 +663,37 @@ finally {
             <intProp name="Assertion.test_type">16</intProp>
           </ResponseAssertion>
           <hashTree/>
+        </hashTree>
+        <JMSSampler guiclass="JMSSamplerGui" testclass="JMSSampler" 
testname="JMS-P2P-Timeout" enabled="true">
+          <stringProp 
name="JMSSampler.queueconnectionfactory">ConnectionFactory</stringProp>
+          <stringProp 
name="JMSSampler.SendQueue">dynamicQueues/requestQueue7</stringProp>
+          <stringProp name="JMSSampler.ReceiveQueue"></stringProp>
+          <intProp name="JMSSampler.communicationStyle">1</intProp>
+          <boolProp name="JMSSampler.isNonPersistent">false</boolProp>
+          <boolProp name="JMSSampler.useReqMsgIdAsCorrelId">true</boolProp>
+          <stringProp name="JMSSampler.timeout">2000</stringProp>
+          <stringProp 
name="JMSSampler.jmsNumberOfSamplesToAggregate"></stringProp>
+          <stringProp name="HTTPSamper.xml_data">test</stringProp>
+          <stringProp 
name="JMSSampler.initialContextFactory">org.apache.activemq.jndi.ActiveMQInitialContextFactory</stringProp>
+          <stringProp 
name="JMSSampler.contextProviderUrl">tcp://localhost:61616</stringProp>
+          <elementProp name="JMSSampler.jndiProperties" 
elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" 
testname="User Defined Variables" enabled="true">
+            <collectionProp name="Arguments.arguments"/>
+          </elementProp>
+          <elementProp name="arguments" elementType="JMSProperties">
+            <collectionProp name="JMSProperties.properties"/>
+          </elementProp>
+          <boolProp name="JMSSampler.useResMsgIdAsCorrelId">true</boolProp>
+        </JMSSampler>
+        <hashTree>
+          <ResponseAssertion guiclass="AssertionGui" 
testclass="ResponseAssertion" testname="RA_noMessage" enabled="true">
+            <collectionProp name="Asserion.test_strings">
+              <stringProp name="1882001775">No reply message 
received</stringProp>
+            </collectionProp>
+            <stringProp 
name="Assertion.test_field">Assertion.response_message</stringProp>
+            <boolProp name="Assertion.assume_success">true</boolProp>
+            <intProp name="Assertion.test_type">16</intProp>
+          </ResponseAssertion>
+          <hashTree/>
         </hashTree>
       </hashTree>
       <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" 
testname="TG-JMS-PS" enabled="true">

Modified: jmeter/trunk/bin/testfiles/JMS_TESTS.xml
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/bin/testfiles/JMS_TESTS.xml?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- jmeter/trunk/bin/testfiles/JMS_TESTS.xml (original)
+++ jmeter/trunk/bin/testfiles/JMS_TESTS.xml Tue Nov 28 21:06:45 2017
@@ -99,6 +99,13 @@
     <error>false</error>
   </assertionResult>
 </sample>
+<sample s="true" lb="JMS-P2P-Timeout" rc="" rm="No reply message received" 
tn="TG-JMS-P2P 1-1" dt="text" sc="1" ec="0" ng="1" na="1">
+  <assertionResult>
+    <name>RA_noMessage</name>
+    <failure>false</failure>
+    <error>false</error>
+  </assertionResult>
+</sample>
 <sample s="true" lb="JMS Publisher-NonDurable" rc="200" rm="1 messages 
published" tn="TG-JMS-PS 2-1" dt="" sc="1" ec="0" ng="1" na="1">
   <assertionResult>
     <name>Response Assertion</name>

Modified: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/FixedQueueExecutor.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/FixedQueueExecutor.java?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/FixedQueueExecutor.java
 (original)
+++ 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/FixedQueueExecutor.java
 Tue Nov 28 21:06:45 2017
@@ -95,10 +95,11 @@ public class FixedQueueExecutor implemen
             // This used to be request.wait(timeout_ms), where 0 means forever
             // However 0 means return immediately for the latch
             if (timeout == 0){
+                log.debug("Waiting infinitely for message");
                 countDownLatch.await(); //
             } else {
                 if(!countDownLatch.await(timeout, TimeUnit.MILLISECONDS)) {
-                    log.debug("Timeout reached before getting a reply 
message");
+                    log.debug("Timeout {} ms reached before getting a reply 
message", timeout);
                 }
             }
             log.debug("{} done waiting for {} on {} ended on {}",
@@ -110,4 +111,9 @@ public class FixedQueueExecutor implemen
         }
         return admin.get(id);
     }
+
+    @Override
+    public void close() throws JMSException {
+        // NOOP
+    }
 }

Modified: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/JMSSampler.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/JMSSampler.java?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/JMSSampler.java
 (original)
+++ 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/JMSSampler.java
 Tue Nov 28 21:06:45 2017
@@ -43,6 +43,7 @@ import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.jmeter.config.Arguments;
 import org.apache.jmeter.protocol.jms.Utils;
 import org.apache.jmeter.samplers.AbstractSampler;
@@ -678,7 +679,7 @@ public class JMSSampler extends Abstract
                 producer.setTimeToLive(Long.parseLong(getExpiration()));
             } else {
                 if (useTemporyQueue()) {
-                    executor = new TemporaryQueueExecutor(session, sendQueue);
+                    executor = new TemporaryQueueExecutor(session, sendQueue, 
getTimeoutAsInt());
                 } else {
                     producer = session.createSender(sendQueue);
                     executor = new FixedQueueExecutor(producer, 
getTimeoutAsInt(), isUseReqMsgIdAsCorrelId());
@@ -755,10 +756,12 @@ public class JMSSampler extends Abstract
     }
 
     private int getTimeoutAsInt() {
-        if (getPropertyAsInt(TIMEOUT) < 1) {
+        String propAsString = getPropertyAsString(TIMEOUT);
+        if(StringUtils.isEmpty(propAsString)){
             return DEFAULT_TIMEOUT;
+        } else {
+            return Integer.parseInt(propAsString);
         }
-        return getPropertyAsInt(TIMEOUT);
     }
 
     public String getTimeout() {
@@ -797,6 +800,13 @@ public class JMSSampler extends Abstract
                 // ignore
             }
         }
+        if (executor != null) {
+            try {
+                executor.close();
+            } catch (JMSException e) {
+                LOGGER.error("Error closing executor {}", executor.getClass(), 
e);
+            }
+        }
         Utils.close(session, LOGGER);
         Utils.close(connection, LOGGER);
         if (receiverThread != null) {

Modified: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/QueueExecutor.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/QueueExecutor.java?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/QueueExecutor.java
 (original)
+++ 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/QueueExecutor.java
 Tue Nov 28 21:06:45 2017
@@ -18,12 +18,13 @@
 
 package org.apache.jmeter.protocol.jms.sampler;
 
+import java.io.Closeable;
+
 import javax.jms.JMSException;
 import javax.jms.Message;
 
 /**
  * Executor for (pseudo) synchronous communication. <br>
- * Created on: October 28, 2004
  *
  */
 public interface QueueExecutor {
@@ -43,4 +44,9 @@ public interface QueueExecutor {
             int priority, 
             long expiration) throws JMSException;
 
+    /**
+     * Close the resources
+     * @throws JMSException
+     */
+    void close() throws JMSException;
 }

Modified: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TemporaryQueueExecutor.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TemporaryQueueExecutor.java?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TemporaryQueueExecutor.java
 (original)
+++ 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TemporaryQueueExecutor.java
 Tue Nov 28 21:06:45 2017
@@ -24,14 +24,19 @@ import javax.jms.Queue;
 import javax.jms.QueueRequestor;
 import javax.jms.QueueSession;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * Request/reply executor with a temporary reply queue. <br>
  * 
  * Used by JMS Sampler (Point to Point)
  */
 public class TemporaryQueueExecutor implements QueueExecutor {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(TemporaryQueueExecutor.class);
     /** The sender and receiver. */
-    private final QueueRequestor requestor;
+    private final TimeoutEnabledQueueRequestor requestor;
+    private int timeout;
 
     /**
      * Constructor.
@@ -40,13 +45,15 @@ public class TemporaryQueueExecutor impl
      *            the session to use to send the message
      * @param destination
      *            the queue to send the message on
+     * @param timeoutMs Timeout in millis
      * @throws JMSException
      *             when internally used {@link QueueRequestor} can not be
      *             constructed with <code>session</code> and
      *             <code>destination</code>
      */
-    public TemporaryQueueExecutor(QueueSession session, Queue destination) 
throws JMSException {
-        requestor = new QueueRequestor(session, destination);
+    public TemporaryQueueExecutor(QueueSession session, Queue destination, int 
timeoutMs) throws JMSException {
+        requestor = new TimeoutEnabledQueueRequestor(session, destination);
+        this.timeout = timeoutMs;
     }
 
     /**
@@ -57,6 +64,13 @@ public class TemporaryQueueExecutor impl
             int deliveryMode, 
             int priority, 
             long expiration) throws JMSException {
-        return requestor.request(request);
+        LOGGER.debug("Sending message and waiting for response in Temporary 
queue with timeout {} ms (0==infinite)", 
+                timeout);
+        return requestor.request(request, timeout);
+    }
+
+    @Override
+    public void close() throws JMSException {
+        requestor.close();
     }
 }

Added: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java?rev=1816573&view=auto
==============================================================================
--- 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java
 (added)
+++ 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java
 Tue Nov 28 21:06:45 2017
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.jmeter.protocol.jms.sampler;
+
+import javax.jms.InvalidDestinationException;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TemporaryQueue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>TimeoutEnabledQueueRequestor</code> helper class simplifies making
+ * service requests using the request/reply pattern.
+ *
+ * <P>
+ * The <code>TimeoutEnabledQueueRequestor</code> constructor is given a
+ * non-transacted <code>QueueSession</code> and a destination
+ * <code>Queue</code>. It creates a <code>TemporaryQueue</code> for the
+ * responses and provides a <code>request</code> method that sends the request
+ * message and waits for its reply.
+ *
+ * @since 4.0
+ */
+public class TimeoutEnabledQueueRequestor {
+    private static final Logger logger = 
LoggerFactory.getLogger(TimeoutEnabledQueueRequestor.class);
+    private Session session; // The queue session to which the queue belongs.
+    private TemporaryQueue tempQueue;
+    private MessageProducer sender;
+    private MessageConsumer receiver;
+
+    /**
+     * Constructor for the <code>TimeoutEnabledQueueRequestor</code> class.
+     *
+     * <P>
+     * This implementation assumes the session parameter to be non-transacted,
+     * with a delivery mode of either <code>AUTO_ACKNOWLEDGE</code> or
+     * <code>DUPS_OK_ACKNOWLEDGE</code>.
+     *
+     * @paramsession the <code>QueueSession</code> the queue belongs to
+     * @paramqueue the queue to performthe request/reply call on
+     *
+     * @exception JMSException
+     *                if the JMS provider fails to create the
+     *                <code>TimeoutEnabledQueueRequestor</code> due to some
+     *                internal error.
+     * @exception InvalidDestinationException
+     *                if an invalid queue is specified.
+     */
+    public TimeoutEnabledQueueRequestor(Session session, Queue queue) throws 
JMSException {
+        this.session = session;
+        tempQueue = session.createTemporaryQueue();
+        sender = session.createProducer(queue);
+        receiver = session.createConsumer(tempQueue);
+    }
+
+    /**
+     * Sends a request and waits for a reply. The temporary queue is used for
+     * the <code>JMSReplyTo</code> destination, and only one reply per request
+     * is expected. The method blocks indefinitely until a message arrives!
+     *
+     * @parammessage the message to send
+     *
+     * @return the reply message
+     *
+     * @exception JMSException
+     *                if the JMS provider fails to complete the request due to
+     *                some internal error.
+     */
+    public Message request(Message message) throws JMSException {
+        return request(message, 0);
+    }
+
+    /**
+     * Sends a request and waits for a reply. The temporary queue is used for
+     * the <code>JMSReplyTo</code> destination, and only one reply per request
+     * is expected. The client waits/blocks for the reply until the timeout is
+     * reached.
+     *
+     * @param message
+     *            the message to send
+     * @param timeout
+     *            time to wait for a reply on temporary queue. If you specify 
no
+     *            arguments or an argument of 0, the method blocks indefinitely
+     *            until a message arrives
+     *
+     * @return the reply message
+     *
+     * @exception JMSException
+     *                if the JMS provider fails to complete the request due to
+     *                some internal error.
+     */
+    public Message request(Message message, long timeout) throws JMSException {
+        message.setJMSReplyTo(tempQueue);
+        sender.send(message);
+        return receiver.receive(timeout);
+    }
+
+    /**
+     * Closes the <code>TimeoutEnabledQueueRequestor</code> and its session.
+     *
+     * <P>
+     * Since a provider may allocate some resources on behalf of a
+     * <code>TimeoutEnabledQueueRequestor</code> outside the Java virtual
+     * machine, clients should close them when they are not needed. Relying on
+     * garbage collection to eventually reclaim these resources may not be
+     * timely enough.
+     *
+     * <P>
+     * This method closes the <code>Session</code> object passed to the
+     * <code>TimeoutEnabledQueueRequestor</code> constructor.
+     *
+     * @exception JMSException
+     *                if the JMS provider fails to close the
+     *                <code>TimeoutEnabledQueueRequestor</code> due to some
+     *                internal error.
+     */
+    public void close() throws JMSException {
+        String queueName = tempQueue.getQueueName();
+        try {
+            tempQueue.delete();
+        } catch (Exception e) {
+            logger.error("Error deleting tempQueue {}", queueName);
+        }
+        // publisher and consumer created by constructor are implicitly closed.
+        try {
+            session.close();
+        } catch (Exception e) {
+            logger.error("Error closing session", e);
+        }
+    }
+}

Propchange: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
jmeter/trunk/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/TimeoutEnabledQueueRequestor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1816573&r1=1816572&r2=1816573&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Tue Nov 28 21:06:45 2017
@@ -85,6 +85,7 @@ Summary
     JMeter will move the <code>Mirror Server</code>, <code>Property 
Display</code> and HTTP(s) <code>Test Script Recorder</code> elements as direct 
children of Test Plan. For
     any other element, it will create a <code>Test Fragment</code> element 
called <code>Workbench Test Fragment and move the elements in it</code>.</li>
     <li>Following classes have been dropped 
(<code>org.apache.jmeter.functions.util.ArgumentEncoder</code>, 
<code>org.apache.jmeter.functions.util.ArgumentDecoder</code>), see 
<pr>335</pr></li>
+    <li>In JMS Point-to-Point sampler, setting timeout to 0 will now mean 
infinite timeout while previously it would be switched to 2000 ms, see 
<bugzilla>61829</bugzilla></li>
 </ul>
 <!-- =================== Improvements =================== -->
 
@@ -104,6 +105,7 @@ Summary
     <li><bug>61739</bug>Java Request / JavaSamplerClient : Improve 
<code>org.apache.jmeter.protocol.java.sampler.JavaSamplerContext</code></li>
     <li><bug>61762</bug>Start Next Thread Loop should be used everywhere</li>
     <li><bug>61544</bug>JMS Point-to-Point Sampler: Enhance communication 
styles with read, browse, clear. Based on a contribution by Benny van 
Wijngaarden (benny at smaragd-it.nl)</li>
+    <li><bug>61829</bug>JMS Point-to-Point : If Receive Queue is empty and a 
timeout is set, it is not taken into account. Contributed by Ubik Load Pack 
(support at ubikloadpack.com)</li>
 </ul>
 
 <h3>Controllers</h3>


Reply via email to