3 Replies Latest reply on Nov 2, 2012 4:50 PM by csa

    CLIENT_ERROR_SUBJECT callback ist not called at all

    sven.plath

      Hi again,

       

      I am struggling with a problem regarding detecting the connection status on client side to create some kind of offline mode (for restoring and re-subscribing again later).

       

      private void subscribeOnErrorBus() {
              bus.subscribe(DefaultErrorCallback.CLIENT_ERROR_SUBJECT, new MessageCallback() {
                  
                  @Override
                  public void callback(Message message) {
                      logger.log(Level.SEVERE, "CLIENT_ERROR_SUBJECT");
                  }
              });
      }
      

       

      I am using the snippet above during the @PostConstruct phase of the Module to add a listener to the CLIENT_ERROR_SUBJECT bus. From my understanding, it should get notified when a message that uses defaultErrorHandling fails under any circumstances, including the hidden heartbeat connection-keepalive stuff.

       

      However the problem is:

      • I don't see when a message generated myself cannot reach the host due to a link down.
      • I don't see when a heartbeat fails.
      • I seriously don't see anything at all. I tried everything to bring up problems, but the callback was never ever called.

       

      What am I doing wrong? I use JBoss AS7, GWT 2.4.0 and Errai 2.1.0.Final.

       

      I also tried using the LogAdapter:

       

      ClientMessageBusImpl bus = (ClientMessageBusImpl) ErraiBus.get();
      bus.setLogAdapter(new LogAdapter() ...)
      

       

      but that also is not showing a thing. I am however do NOT use Dev mode.

       

      Thanks,

      Sven

        • 1. Re: CLIENT_ERROR_SUBJECT callback ist not called at all
          csa

          Hi Sven,

           

          I have looked into this now. The reason the default error callback (CLIENT_ERROR_SUBJECT) is not called is because the browser seems to return an HTTP status code of 0 when a long polling request is interrupted. We became tolerant of this to support window redirects at some point. This is a bug as we should still send a message to the CLIENT_ERROR_SUBJECT in this case. We'll fix this asap.

           

          However, you can register a transport error handler which works fine for the use cases you described (just tested this in both dev and prod. mode)

           

          {code}

          ((ClientMessageBus)bus).addTransportErrorHandler(new TransportErrorHandler() {

                  @Override

                  public void onError(TransportError error) {

                   

                  }

          });

          {code}

           

          Cheers,

          Christian

          • 2. Re: CLIENT_ERROR_SUBJECT callback ist not called at all
            sven.plath

            Hello,

             

            thanks for your elaboration. However your solution seems not to work for me at all. I guess my explanation was a bit clumsy.

            The client needs to:

            • recover from a server-down
            • recover from short connection losses to the server (seconds to minute)
            • recover from long connection losses (minutes to days)

            I have tried various things to get notified:

            • DEFAULT_ERROR_SUBJECT
            • TransportErrorHandler
            • LogAdapter
            • SessionExpirationListener

             

            My observations are:

            Case A: Server terminated.

            1. TransportErrorHandler gets called, prints out error code 12152
            2. CLIENT_ERROR_SUBJECT gets called
            3. LogAdapter gets called

            Case B: Link is down for a long time, no self implemented heartbeat system

            1. Unsubscription events are fired on the server after some time
            2. Client sees nothing at all

            Case C: Link is down for a long time, self implemented heartbeat system (see bottom of this post for explanation)

            1. Unsubscription events are fired on the server after some time
            2. SessionExpiration on clients
            3. LogAdapter is called

                 When the links is back, on the server there are several messages:

            08:30:15,589 ERROR [org.jboss.stdio.AbstractLoggingWriter] *** Message delivery failure ***
            08:30:15,589 ERROR [org.jboss.stdio.AbstractLoggingWriter] Bus: org.jboss.errai.bus.server.ServerMessageBusImpl@6f14d6
            08:30:15,589 ERROR [org.jboss.stdio.AbstractLoggingWriter] Message: ReplyTo=MonitoringService:RespondTo:47, ToSubject=MonitoringService
            08:30:15,589 ERROR [org.jboss.stdio.AbstractLoggingWriter] errorMessage: Error calling remote service: MonitoringService
            08:30:15,589 ERROR [org.jboss.stdio.AbstractLoggingWriter] exception: org.jboss.errai.bus.client.api.base.MessageDeliveryFailure: unable to deliver message: no queue available to send. (queue or session may have expired): (session id: bd142e35e85e1e0cee3ec8c09b5ddea1de4b3a385ab489935e312f7b7db9)
            08:30:15,589 ERROR [org.jboss.stdio.AbstractLoggingWriter] disconnect: false
            08:30:15,605 ERROR [org.jboss.stdio.AbstractLoggingWriter] org.jboss.errai.bus.server.QueueUnavailableException: no queue available to send. (queue or session may have expired): (session id: 2177edff95b06ca690ce64c4e5aa5f6db315dc9a7d349ecc9993bd7c334)
            

            Case D: Links is down for a short time, self implemented heartbeat system

            1. Heartbeats are restored, sessions are kept, everything is fine.

             

            Heartbeats:

            From my understanding, the bus has a heartbeat system that keeps the connection alive. These heartbeats are exchanged in the background as described here:

                 http://docs.jboss.org/errai/2.1.0.Final/errai/reference/html/sid-5931263.html#sid-5931315_QueueSessions-Lifecycle

            But this comment makes me unsecure:

                 https://issues.jboss.org/browse/ERRAI-66

            How is the heartbeat system working?

            My self implemented heartbeat:

            On Client:

            Timer timer = new Timer() {
                        
                        @Override
                        public void run() {
                            logger.info("Heartbeat");
                            MessageBuilder.createMessage()
                                .toSubject("MonitoringService")
                                .with(MessageParts.ReplyTo, "ClientEndpoint")
                                .defaultErrorHandling()
                                .repliesTo(new MessageCallback() {
                                    
                                    @Override
                                    public void callback(Message message) {
                                        logger.info("Heartbeat callback");
                                    }
                                })
                                .sendNowWith(bus);
                        }
                    };
                    timer.scheduleRepeating(5000);
            

            On server:

             

            @Service
            public class MonitoringService implements MessageCallback {
                private static final Logger logger = Logger.getLogger(MonitoringService.class);
                
                @Override
                public void callback(Message message) {
                    // TODO Auto-generated method stub
                    logger.info("Monitoring service...");
                    MessageBuilder.createConversation(message)
                        .subjectProvided()
                        .signalling()
                        .defaultErrorHandling()
                        .reply();
                }
            }
            

            On client log output: (No transport error)

            Fri Oct 05 08:28:47 GMT+200 2012 Theater INFO: Act displayed for: 10

            Fri Oct 05 08:28:51 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:28:56 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:02 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:07 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:12 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:17 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:22 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:27 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:32 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:37 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:42 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:47 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:52 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:29:57 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:30:02 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:30:07 GMT+200 2012 Theater INFO: Heartbeat

            Fri Oct 05 08:30:07 GMT+200 2012 Theater SEVERE: Session expired

            Fri Oct 05 08:30:07 GMT+200 2012 Theater SEVERE: Error LogAdapter

            Fri Oct 05 08:30:07 GMT+200 2012 Theater SEVERE: receiver 'ClientBus' threw an exception -- Additional Details: <table><thead style='font-weight:bold;'><tr><td>Field</td><td>Value</td></tr></thead><tbody><tr><td>ToSubject</td><td>ClientBus</td></tr><tr><td>CommandType</td><td>SessionExpired</td></tr></tbody></table>

            Fri Oct 05 08:30:12 GMT+200 2012 Theater INFO: Heartbeat

             

             

            Conclusion:

            I guess i could use the self implemented heartbeat system to fulfill my requirements, i however thought that something similar was available inside Errai.

            I don't quite understand why I only get SessionExpiration when I constantly talk to the server.

            Additionally, the Heartbeat I described above should throw some error, doesn't it? I mean, the message does not get through. Is there a timeout available?

             

            Regards,

            Sven

            • 3. Re: CLIENT_ERROR_SUBJECT callback ist not called at all
              csa

              Hi Sven,

               

              Sorry for the delay.

               

              We have just added a new bus lifecycle listener which should make this a lot easier. It enables your app to receive events when the bus goes online or offline (e.g. due to a transport error). The bus has always tried to recover from short connection losses (currently 5 retries after 2 seconds each) and will now fire a different event when it gives up. All the details are documented on the new BusLifecycleListener:

               

              https://github.com/errai/errai/blob/master/errai-bus/src/main/java/org/jboss/errai/bus/client/api/BusLifecycleListener.java

               

              If you upgrade to 2.2.0-SNAPSHOT you can already use the feature. Your feedback is more than welcome!

               

              To attach a lifecycle listener just call:

               

              {code}

              ((ClientMessageBus)bus).addLifecycleListener(...)

              {code}

               

              and provide either a listener or a BusLifecycleAdapter instance.

               

              The event objects passed to the listener methods will likely change next week to contain more contextual information (e.g error details). If you like to request changes or have ideas, please let us know. This is work in progress.

               

              Here's the JIRA: https://issues.jboss.org/browse/ERRAI-416

               

              Thanks,

              Christian