[[qbean_support]]

== QBeanSupport

All the details described in our first implementation of +QTest+ can be
simplified by just extending link:https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/q2/QBeanSupport.java[QBeanSupport].

+QBeanSupport+ implement the +QBean+ life-cycle methods +init()+, +start()+,
+stop()+ and +destroy()+ and call the protected:

* initService
* startService
* stopService
* destroyService

providing suitable default implementations for those. These methods are
implemented like this:

[source,java]
----
    public void init () {
        if (state == -1) {
            setModified (false);
            try {
                initService();
                state = QBean.STOPPED;
            } catch (Throwable t) {
                log.warn ("init", t);
            }
        }
    }

    public synchronized void start() {
        if (state != QBean.DESTROYED &&
            state != QBean.STOPPED   &&
            state != QBean.FAILED)
           return;

        this.state = QBean.STARTING;

        try {
           startService();
        } catch (Throwable t) {
           state = QBean.FAILED;
           log.warn ("start", t);
           return;
        }
        state = QBean.STARTED;
    }

    public synchronized void stop () {
        if (state != QBean.STARTED)
           return;
        state = QBean.STOPPING;
        try {
           stopService();
        } catch (Throwable t) {
           state = QBean.FAILED;
           log.warn ("stop", t);
           return;
        }
        state = QBean.STOPPED;
    }

    public void destroy () {
        if (state == QBean.DESTROYED)
           return;
        if (state != QBean.STOPPED)
           stop();

        if (scheduledThreadPoolExecutor != null) {
            scheduledThreadPoolExecutor.shutdown();
            scheduledThreadPoolExecutor = null;
        }
        try {
           destroyService();
        }
        catch (Throwable t) {
           log.warn ("destroy", t);
        }
        state = QBean.DESTROYED;
    }

----

You can see that they track and validate the state of the QBean, 
catch exceptions providing reasonable logging, etc.

In addition, +QBeanSupport+ implements +Configurable+ and exposes
a +public Configuration getConfiguration()+ method. It has a +setServer(Q2)+
method so your implementation can call +getServer()+ to get a reference
to the Q2 system. 

It also implements a +boolean running()+ method so that your QBean
can check if the QBean is still running and get out of a running loop.

+QBeanSupport+ provides a handy +QBeanSupportMBean+ so if your QBean
does not expose any JMX attribute, you don't even have to write an
+xxxMBean+ interface.

Our +Qtest+ implementation could look like this:

[source,java]
----
package org.jpos.test;

import org.jpos.iso.ISOUtil;
import org.jpos.q2.QBeanSupport;

public class QTest extends QBeanSupport implements Runnable {
    @Override
    protected void startService() {
        new Thread(this).start();
    }
    public void run () {
        for (int tickCount=0; running (); tickCount++) {
            log.info ("tick " + tickCount);
            ISOUtil.sleep (cfg.getLong("tickInterval", 1000L));   <1>
        }
    }
}
----
<1> In this case, we are pulling the tickInterval from a 'property' with
    a default to 1 second. We can off course add a +tickInterval+
    attribute and expose it in a +QTestMBean+ interface as described in
    the previous section.

