0

We have the following transaction that sends a heartbeat while it is a running. However in certain situations the heartbeat timer never stops, and the system keeps sending heartbeats even if the transaction is not running. Are we doing something incorrectly here? Is there a more sure shot way of stopping the heart beat timer (other than stopping jboss)?

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Asynchronous
    public void performUpdate(long requestSettingId) throws exception {
        try {
            // At this line a new Thread will be created
            final Timer timer = new Timer();
            // send the first heartbeat
            workerService.sendHeartBeat(requestSettingId);
            // At this line a new Thread will be created
            timer.schedule(new HeartbeatTask(setting.getId()), heartBeatInterval, heartBeatInterval);

            try {
                //Perform update
                //

            } finally {
                // terminate the HeartbeatTask
                timer.cancel();
            } catch (Exception e) {
            //Notify the task owner of the exception   
            }    
        }

    }
Saqib Ali
  • 3,953
  • 10
  • 55
  • 100
  • 1
    Are you sure that complies? I think that you have your brackets mixed up. – Aurand Oct 12 '13 at 15:50
  • why are you using separate nested try's ? Anyhow ? Are you sure the timer.schedule() actually exits ? – Bhanu Kaushik Oct 12 '13 at 15:51
  • @Aurand, sorry i missed a bracket while copying and pasting. The code compiles and works fine in 99% of the time. But only in rare conditions the heartbeat timer doesn't stop. – Saqib Ali Oct 12 '13 at 15:56
  • 1
    What you definitely have in there is a thread leak: if `sendHeartBeat` fails, you don't cancel the Timer. Your try-finally must start immediately after `new Timer()`. – Marko Topolnik Oct 12 '13 at 16:34
  • Thanks @MarkoTopolnik! I am trying that approach right now. – Saqib Ali Oct 12 '13 at 18:55

1 Answers1

1

You finally block need to belong to the outer try, not to the inner try. If timer.schedule fails then your finally block is never executed. Something like:

    public void performUpdate() throws exception {
    Timer timer = null;
    try {
        // At this line a new Thread will be created
        timer = new Timer();

        try {
            timer.cancel();
        } catch (Exception e) {
            //Notify the task owner of the exception
        }
    } finally {
        if ( timer != null ) timer.close();
    }
}
matt helliwell
  • 2,574
  • 16
  • 24