13 Replies Latest reply on May 1, 2012 5:23 PM by ajitnair

    Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1

    ajitnair

      Hi,

       

      We have a client-server application that currently uses Errai 1.3.2.Final. I'm trying to use the newer 2.0CR1 release and am having trouble upgrading to it. It appears our Errai RPC calls aren't being executed. Using Firebug in Firefox, we can see that the Errai heartbeats are working fine. But for the RPC calls we are seeing error messages like this:

       

      [errai] [error] failed to transmit deferred message: CommandType=readAllTableNames:, .....

      [errai]     -> no subscribers to deliver to for subject: .......

       

      It seems the client isn't seeing the RPC server.

       

      We use both Spring and Guice in our code. Our setup is as follows:

       

      1. We first instantiate Guice and bind the Errai classes to it like this:

       

      // Manually bind Errai required classes in a Guice Injector.

      Injector guiceInjector = Guice.createInjector(new AbstractModule() {

           public void configure() {

                bind(MessageBus.class).to(ServerMessageBusImpl.class);

                bind(ServerMessageBus.class).to(ServerMessageBusImpl.class);

                bind(ErraiServiceConfigurator.class).to(ErraiServiceConfiguratorImpl.class);

                bind(ErraiService.class).to(ErraiServiceImpl.class);

           }

        });

       

      2. Then we setup the service locator like this:

       

        // Trigger initialization of the Errai Bus by requesting an instance of ErraiService.

      @SuppressWarnings("rawtypes")

      ErraiService erraiService = guiceInjector.getInstance(ErraiService.class);

             

      // Place the application level singleton instance of ErraiService in a place that the

      // Errai Servlet can later find it.

      OurErraiServiceLocator.setErraiService(erraiService);

       

      where OurErraiServiceLocator implements the ServiceLocator interface.

       

      3. Then the Spring container is initialized where all of our Services are wired into the app.

       

      4. And finally we register all the services now loaded in the Spring container with Errai. For each method in each service we create a bind point like this:

      String bindPoint = RebindUtils.createCallSignature(serviceMethod); and then add it to a map (named messageEndpoints) with a callback like this:

       

      messageEndpoints.put(bindPoint,

             new ConversationalEndpointCallback(

                   new ServiceInstanceProvider() {   <---- This used to be of type Provider<T> in the code using v1.3.2

                        @Override

                        public Object get(Message msg) { <--------- This used to be an empty parameter list in 1.3.2

                             return springServiceBean; <------------ THis is the bean obtained from the Spring container

                        }

                   }, serviceMethod, erraiMessageBus));

       

      And finally we register the map with Errai like this:

      5. erraiMessageBus.subscribe(remoteInterface.getName() + ":RPC", new RemoteServiceCallback(messageEndpoints));

       

      Is this the right way to be registering Errai RPC services that were loaded in Spring? It has been working fine when using Errai 1.3.2. Or is there another way to be doing this?

       

      Should we be registering the RPC services differently in 2

        • 1. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
          csa

          In CR1 the default for auto service discovery has changed which is what could cause this issue. You now have to explicitly turn on service discovery in your web.xml for plain bus applications (Errai applications not using CDI).

           

          See the upgrade guide for details: http://docs.jboss.org/errai/2.0.CR2/errai/reference/html_single/#sid-24838246

          • 2. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
            ajitnair

            That helped a little but I'm still getting the NoSubscribersToDeliver exception when the client calls a Errai RPC method. Turning on auto discovery helped in that I am now seeing the error message in the gwt-log remote logger (which I wasn't earlier). Looks like auto discovery helped discover the remote logger servlet. However, the RPC calls are still failing. Is there anything different in how I should be registering the RPC calls with Errai?

            • 3. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
              csa

              Are the RPCs never reaching the server or is the reply failing to reach the client? The error really only means that the bus receiving the message did not find a subscription for it. Can you verify that the bus instance you are calling subscribe on is the same that receives the message? Also, I assume you have recompiled your clients with 2.0?

              • 4. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                ajitnair

                Yes I am compiling with the 2.0 libraries. I followed the instruction set in the document for upgrading from 1.x to 2.0.

                 

                The RPC calls from the client were not reaching the server. Other messages (such as createMessage() and createConversation()) seem to be working fine. It's just the RPC calls - createCall(). I verified that the names being registered are the same as well.

                 

                I've made some progress from my last email. I found a problem in our code. Since we're using the Spring framework, our server side classes were annotated with the Spring @Service annotation, not the Errai @Service. This had been working with the Errai 1.3.2Final libraries, but maybe the 2.0 libraries perform stricter validation? Anyway, I went ahead and added the Errai annotation and now I see that the call from the client is making it to the server, which is good, but Spring seems to be confused and is not auto-wiring the components of those objects. So I'm now getting NullPointerExceptions when the server method gets executed.

                 

                It's possible that I need to order the invocation of Spring and Errai differently. I'm looking into that right now. But if you have any ideas, that would be appreciated.

                • 5. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                  ajitnair

                  I think what's happening is that with both @Service annotations, both Spring and Errai are instantiating objects of the same type. But the auto-wiring that we depend on in the implementation of the methods, is done in the Spring instantiated object, not the Errrai instantiated object. But since the RPC call gets invoked on the Errai instantiated object, the call fails since none of the members of the object have been wired.

                   

                  When we used the 1.3.2Final library, we didn't used auto-discovery in Errai and instead made Spring and Errai work together (as I described in my first post). In short what we did was:

                  - instantiate Spring context

                  - instantiate Guice and Errai

                  - for all our services that were instantiated by Spring, interate through their interface and subscribe them as endpoints with Errai so that Errai thinks these are RPC service endpoints.

                   

                  It looks like that method doesn't work with the 2.0CR1 library - specifically that last part of subscribing endpoints with Errai programmatically.

                   

                  What we want to do is have Spring manage the objects (i.e. instantiate them, auto-wire them, etc) but have Errai use those objects when servicing a RPC call. Is there a different process you know of that we should be following?

                  • 6. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                    csa

                    Yeah I understand. So, when you turn off auto-discovery and subscribe to the service yourself, can you verify the bus instance you subscribed on is the same as the one which received the in-coming message? In our service processor we use the bus instance provided by the BootstrapContext.

                    • 7. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                      ajitnair

                      When I turn off auto-discovery and subscribe the services myself, the call from the client never gets to the server. Instead, the client reports a NoSubscribersToDeliver exception.

                       

                      And when I turn on auto-discovery (even if I subscribe the services programmatically), it looks like there are two instances of the service object (Errai and Spring). I'll try to get the message bus instance from the server object when its methos gets invoked - is that what you're asking for? I assume there's an API for me to get to the message bus object from within the server method?

                      • 8. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                        csa

                        <When I turn off auto-discovery and subscribe the services myself, the call from the client never gets to the server. Instead, the client reports a NoSubscribersToDeliver exception.>

                        Yes, that's because the server bus communicates the subscriptions to the client on startup, which is why I think the bus instance you subscribe to is not the one used by Errai. The client does then not even bother sending the messages because there are no subscribers.

                         

                        <And when I turn on auto-discovery (even if I subscribe the services programmatically), it looks like there are two instances of the service object (Errai and Spring).>

                        Yes, you will end up with two instances of your Service, the one that you created plus the one created by Errai.

                         

                        So, you need to make sure you only have one Service instance and bus instance in your app. Take a look at ErraiServiceSingleton: It will provide you with an ErraiService instance that in turn provides access to the bus instance.

                        • 9. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                          ajitnair

                          The instance of ServerMessageBus reported by ErraiService via ErraiServiceSingleton is indeed different from the instance that I'm creating and inializing with the RPC endpoints.

                           

                          I guess I have to figure out how I can either inject the MessageBus I'm creating into Errai.

                           

                          Either that or I need to delay the initializing of the RPC endpoints until such time that ErraiServiceSingleton has been created (and initialized) and then get a reference to the ServerMessageBus. At this point I could initialize the RPC endpoints with the message bus.

                           

                          Can you recommend an insertion point in the startup of the Errai servlet where I can do this? i.e. get a reference to the ServerMessageBus to do the RPC endpoints and to provide it to our Spring container?

                          • 10. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                            csa

                            Yes, that's the problem then. You could override your ErraiServlet's init method. After calling super.init, the ErraiServiceSingleton should be initialized.

                            • 11. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                              ajitnair

                              So the ErraiServlet creates the MessageBus (during its init) and I'd access it after initializing the servlet. That should work. I'll have to restructure our code so that we startup the ErraiServlet first and then the rest of the code that initializes the Spring container.

                               

                              But do you know if there's a way for me to inject a MessageBus that I create, into the ErraiServlet so that it uses that bus instead of creating a new one? If I could do that, I might not have to restructure my code.

                              • 12. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                                csa

                                No, the latter is currently not possible.

                                • 13. Re: Errai RPC problems when upgrading from 1.3.2Final to 2.09CR1
                                  ajitnair

                                  Good to know.

                                   

                                  Thanks for all your help!