title: Atmosphere @Disconnect does not get called when we close browser window
body: <p>Using the chat example, when I close the browser window, I do not ever see the @Disconnect method called. </p>
  
  <p>Here is my service:-</p>
  
  <pre><code>package org.atmosphere.samples.chat;
  
  import java.io.IOException;
  
  import org.atmosphere.config.service.Disconnect;
  import org.atmosphere.config.service.ManagedService;
  import org.atmosphere.config.service.Ready;
  import org.atmosphere.cpr.AtmosphereResource;
  import org.atmosphere.cpr.AtmosphereResourceEvent;
  import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  @ManagedService(path = "{room: [a-zA-Z][a-zA-Z_0-9]*}")
  public class Chat
  {
      private static final Logger LOGGER = LoggerFactory.getLogger(Chat.class);
  
      @Ready
      public void onReady(final AtmosphereResource inAtmosphereResource)
      {
          LOGGER.info("Browser {} connected.", inAtmosphereResource.uuid());
      }
      @Disconnect
      public void onDisconnect(AtmosphereResourceEvent event)
      {
          if (event.isCancelled())
          {
              LOGGER.info("Browser {} unexpectedly disconnected", event.getResource().uuid());
          }
          else if (event.isClosedByClient())
          {
              LOGGER.info("Browser {} closed the connection", event.getResource().uuid());
          }
          else
          {
              LOGGER.info("close event was called, but I know not why");
          }
      }
  
      @org.atmosphere.config.service.Message(encoders = { JacksonEncoder.class }, decoders = { JacksonDecoder.class })
      public Message onMessage(Message message) throws IOException
      {
          LOGGER.info("{} just send {}", message.getAuthor(), message.getMessage());
          return message;
      }
  }
  </code></pre>
  
  <p>Here is my JS:-</p>
  
  <pre><code>$(function () {
  "use strict";
  
  var header = $('#header');
  var content = $('#content');
  var input = $('#input');
  var status = $('#status');
  console.log(document.location.hash);
  var bookingNumber = document.location.hash.substring(1, document.location.hash.length);
  console.log(bookingNumber);
  var myName = false;
  var author = null;
  var logged = false;
  var socket = $.atmosphere;
  var subSocket;
  var transport = 'websocket';
  
  // We are now ready to cut the request
  var request = { url: document.location.toString().replace(/#.*/, "") + 'chat/' + bookingNumber,
      contentType : "application/json",
      trackMessageLength : true,
      shared : true,
      logLevel : "debug",
      transport : transport ,
      fallbackTransport: 'long-polling'};
  
  request.onOpen = function(response) {
      content.html($('&gt;p&lt;', { text: 'Atmosphere connected using ' + response.transport }));
      input.removeAttr('disabled').focus();
      status.text('Choose name:');
      transport = response.transport;
  
      if (response.transport == "local") {
          subSocket.pushLocal("Name?");
      }
  };
  
  request.onTransportFailure = function(errorMsg, request) {
      jQuery.atmosphere.info(errorMsg);
      if (window.EventSource) {
          request.fallbackTransport = "sse";
          transport = "see";
      }
      header.html($('&lt;h3&gt;', { text: 'Atmosphere Chat. Default transport is WebSocket, fallback is ' + request.fallbackTransport }));
  };
  
  request.onMessage = function (response) {
  
      // We need to be logged first.
      if (!myName) return;
  
      var message = response.responseBody;
      try {
          var json = jQuery.parseJSON(message);
      } catch (e) {
          console.log('This doesn\'t look like a valid JSON: ', message.data);
          return;
      }
  
      if (!logged) {
          logged = true;
          status.text(myName + ': ').css('color', 'blue');
          input.removeAttr('disabled').focus();
          subSocket.pushLocal(myName);
      } else {
          input.removeAttr('disabled');
  
          var me = json.author == author;
          var date = typeof(json.time) == 'string' ? parseInt(json.time) : json.time;
          addMessage(json.author, json.message, me ? 'blue' : 'black', new Date(date));
      }
  };
  
  request.onClose = function(response) {
      logged = false;
  }
  
  subSocket = socket.subscribe(request);
  input.keydown(function(e) {
      if (e.keyCode === 13) {
          var msg = $(this).val();
          if (author == null) {
              author = msg;
          }
  
          subSocket.push(jQuery.stringifyJSON({ author: author, message: msg }));
          $(this).val('');
  
          input.attr('disabled', 'disabled');
          if (myName === false) {
              myName = msg;
          }
      }
  });
  
  function addMessage(author, message, color, datetime) {
      content.append('&lt;p&gt;&lt;span style="color:' + color + '"&gt;' + author + '&lt;/span&gt; @ ' +
          + (datetime.getHours() &lt; 10 ? '0' + datetime.getHours() : datetime.getHours()) + ':'
          + (datetime.getMinutes() &lt; 10 ? '0' + datetime.getMinutes() : datetime.getMinutes())
          + ': ' + message + '&lt;/p&gt;');
      }
  });
  </code></pre>
  
  <p>I am running on glassfish 3, with web sockets and comet enabled.</p>
  
  <p><em>UPDATE</em> I forgot to mention that I am using v 2.1.0RC1</p>