Bug 477622

Summary: Feature request java client heart beat (IG Index)
Product: Red Hat Enterprise MRG Reporter: Arnaud Simon <asimon>
Component: qpid-javaAssignee: Rajith Attapattu <rattapat+nobody>
Status: CLOSED ERRATA QA Contact: Frantisek Reznicek <freznice>
Severity: medium Docs Contact:
Priority: urgent    
Version: 1.1CC: cctrieloff, esammons, gsim, iboverma
Target Milestone: 1.1.1   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard: IG Index
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2009-04-21 16:17:11 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Arnaud Simon 2008-12-22 14:55:45 UTC
Some applications may have to deal with clients that are inactive for a long period of time. Such clients may have their connection closed by a firewall. A heart bit mechanism would prevent that to happen. The java client should therefore support a configurable heart bit mechanism.

Comment 2 Rajith Attapattu 2009-02-03 14:45:56 UTC
This is tracked upstream in https://issues.apache.org/jira/browse/QPID-1609
Heartbeat support for the java client has been checked in to trunk in rev 737125.
The current RPMS for MRG 1.1 includes this rev.

Comment 5 Frantisek Reznicek 2009-03-04 15:40:16 UTC
No test info included, could you possibly add, please?

Comment 6 Rajith Attapattu 2009-03-05 15:55:48 UTC
Currently the java client is not sending any HB.
Instead the java client will timeout after 2X secs if it does not receive anything from the broker, where X is the HB interval sent by the broker.
We did have an automated test case for this but we got rid of it as it had some race conditions. 

We could do the following to test it manually.
We can build the java client with say a 10 secs delay hardcorded and then just have a simple JMS client that creates a connection. The broker could use it's default 120 secs HB. The java client should timeout approximately 10 secs after the connection is established.

Comment 7 Frantisek Reznicek 2009-03-05 16:32:48 UTC
Hello Rajith,
I'd like to fully understood your points, could you review my understanding and correct it if necessary, please?

You wrote
  Currently the java client is not sending any HB.
  Instead the java client will timeout after 2X secs if it does not receive
  anything from the broker, where X is the HB interval sent by the broker.
  We did have an automated test case for this but we got rid of it as it had some
  race conditions. 

  We could do the following to test it manually.
  We can build the java client with say a 10 secs delay hardcorded and then just
  have a simple JMS client that creates a connection. The broker could use it's
  default 120 secs HB. The java client should timeout approximately 10 secs
  after the connection is established.

So java client does not sent HB frames, instead of that relies on broker that 
broker itself will send HB to java clients. Every java client has build-in 
connection timeout of 20-30 secs (configurable) which makes sure client stay 
connected with broker if broker is running well, if broker dies/not respond 
then every java client throws connection error exception in next max. 30 secs.

The experiment is to build & execute java client with connection to broker 
which will:
- wait 10 secs
- opens JMS connection
- connection should be exited after about another 10 secs from the moment 
  it created that connection 
  (this is true because broker default HB frame period is 120 secs)


Did I get it correctly?

Which client I might use for that? Is below one suitable for this?

package org.apache.qpid.example.jmsexample.hb_timeout;

import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;


public class HBTimeout
{
    /* Used in log output. */
    private static final String CLASS = "HBTimeout";

    public HBTimeout ()
    {
    }

    public static void main(String[] args)
    {
        // wait 10 secs
        Thread.sleep(10000)
        // create HBTimeout instance
        HBTimeout hbtimeout = new HBTimeout();
        // run the test
        hbtimeout.runTest();
    }

    private void runTest()
    {
        try
        {

            // Load JNDI properties
            Properties properties = new Properties();
            properties.load(this.getClass().getResourceAsStream("direct.properties"));
            //Create the initial context
            Context ctx = new InitialContext(properties);

            // look up destination
            Destination destination = (Destination)ctx.lookup("directQueue");

            // Lookup the connection factory
            ConnectionFactory conFac = (ConnectionFactory)ctx.lookup("qpidConnectionfactory");
            // create the connection
            Connection connection = conFac.createConnection();

            connection.setExceptionListener(new ExceptionListener()
            {
                public void onException(JMSException e)
                {
                    e.printStackTrace();
                }
            });

            // Close the connection to the broker
            System.out.println(CLASS + ": Closing connection");
            connection.close();

            // Close the JNDI reference
            System.out.println(CLASS + ": Closing JNDI context");
            ctx.close();
        }
        catch (Exception exp)
        {
            System.err.println(CLASS + ": Caught an Exception: " + exp);
            exp.printStackTrace();
        }
    }
}

// eof

Comment 8 Rajith Attapattu 2009-03-05 17:38:51 UTC
Here is a better way to test this feature (thx gordon for pointing it out -
also see https://bugzilla.redhat.com/show_bug.cgi?id=461932 for more details)

1. Start the broker and find out the PID/.

2. Start the client (the Consumer from the direct exchange example) as follows

3. java -cp $QPID_CLASSPATH -Didle_timeout=5000
org.apache.qpid.example.jmsexample.direct.Consumer

4. Do the following "kill -STOP <broker_pid>

5. The client should timeout with the following exception in aprox 10 secs
org.apache.qpid.transport.ConnectionException: Read timed out

Notes:
To set the classpath you can do the following
export JAR_PATH=<path_to_qpid_checkout>qpid/java/build/lib/
export QPID_CLASSPATH=`find $JAR_PATH -name "*.jar" | tr "\n" ":"`


Also if you set the failover details in the connection URL then the client
should failover to the other broker.

Comment 9 Gordon Sim 2009-03-05 18:10:27 UTC
Note that you should leave an arbitrary amount of time (> idle_timeout * 2) between steps 3 and 4 to verify that the heartbeats should keep the client connection open.

i.e. the client should timeout 10 secs after the STOP signal is sent, not 10 secs from the time it was connected.

Comment 10 Frantisek Reznicek 2009-03-09 10:13:36 UTC
The feature has been implemented, validated folowing comments #8 and #9 on 
RHEL 4.7, 5.2, 5.3 i386 / x86_64 on packages: qpidd-0.4.750054-1.el5, 
qpid-java-common-0.4.750205-1.el5, qpid-java-client-0.4.750205-1.el5.

->VERIFIED

Comment 12 errata-xmlrpc 2009-04-21 16:17:11 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHEA-2009-0434.html