6 Replies Latest reply on Mar 25, 2014 2:05 PM by vwjugow

    RPC Tests with Errai

    vwjugow

      Hello, we are trying to run integration tests with errai framework that make use of RPC calls, and CDI Events, but we are facing some problems.

      We based our work on this archetype: Errai CDI Maven Archetype - Errai - Project Documentation Editor

      In that archetype there is a test that for Events that works, and we added another that uses RPC calls and also works. However we were unable to replicate this in our project, even copying the exact same tests. Of course we copied the maven profile in the pom, web.xml, the errai*.properties, beans.xml, but still doesn't work.

       

      The tests:

      • RPC

          

      package app.client.local;
      
      
      import app.client.shared.service.AsyncRPCService;
      import org.jboss.errai.bus.client.api.base.MessageBuilder;
      import org.jboss.errai.common.client.api.RemoteCallback;
      import org.jboss.errai.enterprise.client.cdi.AbstractErraiCDITest;
      import org.junit.Test;
      
      
      public class RPCTest extends AbstractErraiCDITest {
      
      
        @Override
        public String getModuleName() {
        return "app.App";
        }
      
      
        @Override
        public void gwtSetUp() throws Exception {
        super.gwtSetUp();
        }
      
      
        @Test
        public void testButtonClickUpdatesLabel() throws Exception {
             System.out.println("-- Testing create strategy --");
             CDITestHelper.afterCdiInitialized(new Runnable() {
                  @Override
                  public void run() {
                       MessageBuilder.createCall(new RemoteCallback<String>() {
                            @Override
                            public void callback(String response) {
                                 System.out.println("-- Got a response! --");
                                 assertEquals("foobar", response);
                                 finishTest();
                            }
                       }, AsyncRPCService.class).doSomeTask();
                  }
             });
             delayTestFinish(20000);
        }
      }
      


      Stack trace: http://pastebin.com/4Y5TH9Gf


      •      CDI
      package app.client.local;
      
      import app.server.SimpleCDIService;
      import org.jboss.errai.enterprise.client.cdi.AbstractErraiCDITest;
      import org.junit.Test;
      
      
      import javax.inject.Inject;
      
      
      /**
       * Tests features of the quickstart application. The primary purpose of this
       * test case is to serve as an example for how to set up real
       * functional/integration tests in a real application.
       * 
       * @author Jonathan Fuerth <jfuerth@gmail.com>
       */
      public class AppIntegrationTest extends AbstractErraiCDITest {
      
      
        /**
         * Reference to the CDI-managed application object {@code CDITestHelper.instance.app}.
         * Initialized in each individual test case in a {@code CDI.addPostInitTask()} block.
         */
        private AppUI app;
        
        @Override
        public String getModuleName() {
          return "app.App";
        }
      
      
        @Override
        public void gwtSetUp() throws Exception {
          super.gwtSetUp();
        }
      
      
        @Test
        public void testInitialSetup() {
         System.out.println("INIT TEST MAGICK");
          CDITestHelper.afterCdiInitialized(new Runnable() {
             @Override
             public void run() {
                  app = CDITestHelper.instance.app;
                  assertNotNull(app.getMessageBox());
                  assertNotNull(app.getResponseLabel());
                  assertNotNull(app.getSendButton());
                  assertEquals("", app.getResponseLabel().getText());
                  System.out.println("ENDED 2 TEST MAGICK");
                  finishTest();
                  System.out.println("ENDED 3 TEST MAGICK");    
             });
              System.out.println("ENDING TEST MAGICK");
      
      
          // This call tells GWT's test runnerwait 20 seconds after the test returns.
          // We need this delay to give the HelloMessage time to come back from the server.
          delayTestFinish(20000);
         System.out.println("ENDED 1 TEST MAGICK");
        }
      
      
        @Test
        public void testButtonClickUpdatesLabel() throws Exception {
        System.out.println("INIT TEST MAGICK");
          CDITestHelper.afterCdiInitialized(new Runnable() {
            @Override
            public void run() {
         System.out.println("POLACOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO2");
              app = CDITestHelper.instance.app;
              app.getResponseLabel().setText("label value before click");
              app.getMessageBox().setText("moocow");
              app.fireMessage();
            }
          });
          
          CDITestHelper.afterResponseEvent(new Runnable() {
            @Override
            public void run() {
                              System.out.println("POLACOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO");
              // this is what we sent
              String messageBoxText = app.getMessageBox().getText();
                   
              // this is composed from the server response message
              String labelText = app.getResponseLabel().getText();
              
              assertTrue("Unexpected label contents after pressing button: \"" + labelText + "\"",
                  labelText.startsWith("HelloMessage from Server: " + messageBoxText.toUpperCase() + " @ TIMEMILLIS: "));
              finishTest();
            }
          });
          
          // This call tells GWT's test runner to wait 3000ms after the test returns.
          // We need this delay to give the HelloMessage time to come back from the server.
          delayTestFinish(3000);
        }
      }
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      

       

           The CDITestHelper is the same as in the archetype, we only changed app field so it is our application's entry point.

       

      The stacktrace: http://pastebin.com/CjTf7N8n

      (first test result is 'passed' but it throws an exception when running the @AfterInitialization methods of our classes.)

       

      And if we add an @Inject SimpleCDIService we get http://pastebin.com/2Sf9aHDk

       

      Here is a list of the things we have tried:

      • Copying from scratch.

                We have the CDI archetype working, even with an injected dummyService. So we tried copying everything (pom, web.xml, Errai*.properties, beans.xml) from that example to appui but still same exception (branch APPUI-812b).

      • Added an AfterInitialization method in Archetype project and it is being executed.
      • Removed every reference to google.inject.Inject from the project but didn’t work.
      • Also tried using google.inject instead of javax.inject.Inject but nothing.
      • Adding <Resource><Directory>src/main/java and src/main/resource<....> in the pom
      • Adding Additional classpath directories in the surefire plugin
      • Commented out everything in UserManagementServiceImpl
      • Created a @Remote interface that extends from WorkItemHandler for UpdateAccountWorkItemHandler
      • Debugged the UI with the same breakpoints. The UI does not stop in those places.
      • Cyclic use of classes: http://pastebin.com/LCZECRAX

       

      If there is anything else I can do to help explain the problem please tell me.





        • 1. Re: RPC Tests with Errai
          csa

          Hi Victor,


          The main problem you have according to your stack traces is that your server doesn't bootstrap correctly (it is not federating with the client-side bus).

           

          I can think of a few possible reasons for this:

           

          - Any of the following dependencies are not deployed (errai-weld-integration, errai-bus, weld-se-core, weld-servlet-core). Is your integration-test profile active when you run the tests?

           

          - Misconfigured web.xml, see errai/errai-cdi/weld-integration/war/WEB-INF/web.xml at master · errai/errai · GitHub for reference (esp. the listener!). This web.xml should be in war/WEB-INF/web.xml when you run your tests.

           

          - Missing beans.xml (should be in war/WEB-INF when you run the tests).

           

          This is the first issue you need to address: Make sure your server is bootstrapping properly when running the tests.

           

          The second issue is that you're trying to inject a server-side class into a client-side bean: http://pastebin.com/2Sf9aHDk. According to your stack trace you tried to @Inject app.server.SimpleCDIService into app.client.local.AppIntegrationTest.

           

          This won't work. All types you use on the client must be translatable to JavaScript (part of a GWT module and in a package that is visible on the client) but like I said let's focus on the first issue for now.

           

          Cheers,

          Christian

          • 2. Re: Re: RPC Tests with Errai
            vwjugow

            Hi Christian, thanks for answering.

             

            • Yes, the integration-test is active, I run test like this: mvn test -Pintegration-test -Denvironment=dev -Dtest=RPCTest

             

            We don't have war directory, but in pom.xml, insde maven-surefire-plugin, within integration-test profile we have this :

             

            <systemProperties>
               <property>
                 <name>errai.hosted_mode_testing</name>
                 <value>true</value>
               </property>
               <property>
                    <name>gwt.args</name>
                    <value>-war src/main/webapp</value>
               </property>
            </systemProperties>
            

             

            Does the -war src/main/webapp saves this ?

            Anyway, I tried adding war directory at the same level as webapp and nothing changed.

             

            • Second, I was missing the listener in the web.xml (have it in src/main/webapp/WEB-INF), don't know why I had it commented. This did help, now the stacktraces changed a little bit, the no subscribers error pops up a little later now. The first error occurs in one of our AfterInitialization methods, and after that the no subscriber error.

            RPCTest: http://pastebin.com/L7ftUXYf

            CDI: almost the same.

             

            The code that fails:

                @AfterInitialization
                public void init() {
                    try {
                        sessionService.call(new RemoteCallback<User>() {
                                                @Override
                                                public void callback(User user) {
                                                    //setUser(user);
                                                    //userEvent.fire(user);
                                                    loggedInUser.setUser(user);
                                                    loggedInUserEvent.fire(loggedInUser);
            
            
                                                }
                                            }, new ErrorCallback<Object>() {
                                                @Override
                                                public boolean error(Object message, Throwable throwable) {
                                                    JSNIHelper.errorNotify(SharedConstants.ERROR_STRING, "Something went wrong when trying to check session user.");
                                                    return false;
                                                }
                                            }
                        ).getCurrentUser();
                    } catch (MGSessionException e) {
                        //TODO: Log this properly
                        e.printStackTrace();
                    }
                }
            

            The 17th line is the one that fails. Suppose that's not strange because that's an invocation to a JSNI method. But it should not enter the ErrorCallback. I debugged and the throwable is the noSubscriberToDeliverTo.

             

            In ClientMessageBus.java, this remotes.containsKey(subject)  gives false when invoking  call(..).getCurrentUser(); subject is "app.client.shared.service.session.SessionService:RPC".

             

            • How can I make sure that my server is bootstrapping properly? I really don't know much about this 'bootstrap' stuff.

             

            • About the second issue, you are right I injected the wrong class, let's leave it for later, but I tried injecting a client service and I got a huge stack trace about concurrent stuff (the most importan part: http://pastebin.com/ES01C2HY)
            • 3. Re: Re: RPC Tests with Errai
              csa

              OK, so now that you commented the Weld listener back in, Jetty and Weld seem to be able to bootstrap (make sure to apply the change in src/main/jetty as well). The problem now is that it can't find an implementation of your AsyncRPCService.

               

              Where is your AsyncRPCServiceImpl? In a JAR? If so, it needs to be deployed as well and have a beans.xml. The type also needs to be annotated with @Service.

              • 4. Re: Re: Re: RPC Tests with Errai
                vwjugow

                mm no it is in the project, main folder, as a java class, and it looks like this:

                 

                package app.server.service;
                
                import app.client.shared.service.AsyncRPCService;
                import org.jboss.errai.bus.client.api.CallableFuture;
                import org.jboss.errai.bus.server.annotations.Service;
                import org.jboss.errai.bus.server.api.CallableFutureFactory;
                import java.util.concurrent.Executors;
                
                /**
                * @author Mike Brock
                */
                @Service
                public class AsyncRpcServiceImpl implements AsyncRPCService {
                  @Override
                  public CallableFuture<String> doSomeTask() {
                       final CallableFuture<String> future = CallableFutureFactory.get().createFuture();
                
                       final java.util.concurrent.ExecutorService executorService = Executors.newSingleThreadExecutor();
                       executorService.submit(new Runnable() {
                            @Override
                            public void run() {
                            try {
                                 Thread.sleep(5000);
                                 future.setValue("foobar");
                            }
                            catch (Throwable t) {
                                 t.printStackTrace();
                            }
                       }
                  });
                  executorService.shutdown();
                  return future;
                  }
                }
                
                • 5. Re: Re: Re: RPC Tests with Errai
                  csa

                  I can't tell what's wrong with your project setup without trying it myself. This seems to be a small example project. If you can share it on GitHub in a minimal setup and runnable state I can give it a try.

                  • 6. Re: Re: Re: RPC Tests with Errai
                    vwjugow

                    mm I can't share it, and the application is huge. And unfortunately I wasn't able to reproduce this problem in a sandbox application. I will try again though, maybe tomorrow.