Fix an NPE in SimpleRequestProcessor when a client request has no invocations.
Issue 5793.
Patch by: bobv
Review by: rchandia
Found by: cory.prowse

Review at http://gwt-code-reviews.appspot.com/1242801


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9479 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java b/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java
index 2fde11d..5eeb6b8 100644
--- a/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java
+++ b/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java
@@ -214,8 +214,7 @@
     // Invoke methods
     List<Splittable> invocationResults = new ArrayList<Splittable>();
     List<Boolean> invocationSuccess = new ArrayList<Boolean>();
-    List<InvocationMessage> invlist = req.getInvocations();
-    processInvocationMessages(source, invlist, invocationResults,
+    processInvocationMessages(source, req, invocationResults,
         invocationSuccess, returnState);
 
     // Store return objects
@@ -225,8 +224,11 @@
     toProcess.putAll(returnState.beans);
     createReturnOperations(operations, returnState, toProcess);
 
-    resp.setInvocationResults(invocationResults);
-    resp.setStatusCodes(invocationSuccess);
+    assert invocationResults.size() == invocationSuccess.size();
+    if (!invocationResults.isEmpty()) {
+      resp.setInvocationResults(invocationResults);
+      resp.setStatusCodes(invocationSuccess);
+    }
     if (!operations.isEmpty()) {
       resp.setOperations(operations);
     }
@@ -409,9 +411,14 @@
   }
 
   private void processInvocationMessages(RequestState state,
-      List<InvocationMessage> invlist, List<Splittable> results,
-      List<Boolean> success, RequestState returnState) {
-    for (InvocationMessage invocation : invlist) {
+      RequestMessage req, List<Splittable> results, List<Boolean> success,
+      RequestState returnState) {
+    List<InvocationMessage> invocations = req.getInvocations();
+    if (invocations == null) {
+      // No method invocations which can happen via RequestContext.fire()
+      return;
+    }
+    for (InvocationMessage invocation : invocations) {
       try {
         // Find the Method
         String[] operation = invocation.getOperation().split("::");
diff --git a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
index b116e1c..b7a0c09 100644
--- a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
@@ -886,6 +886,19 @@
   }
 
   /**
+   * Tests a no-op request.
+   */
+  public void testNoOpRequest() {
+    delayTestFinish(DELAY_TEST_FINISH);
+    simpleFooRequest().fire(new Receiver<Void>() {
+      @Override
+      public void onSuccess(Void response) {
+        finishTestAndReset();
+      }
+    });
+  }
+
+  /**
    * Ensures that a service method can respond with a null value.
    */
   public void testNullEntityProxyResult() {
@@ -1008,7 +1021,7 @@
    */
   public void testNullValueInIntegerListRequest() {
     delayTestFinish(DELAY_TEST_FINISH);
-    List<Integer> list = Arrays.asList(new Integer[]{1, 2, null});
+    List<Integer> list = Arrays.asList(new Integer[] {1, 2, null});
     final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInIntegerList(
         list);
     fooReq.fire(new Receiver<Void>() {
@@ -1024,7 +1037,7 @@
    */
   public void testNullValueInStringListRequest() {
     delayTestFinish(DELAY_TEST_FINISH);
-    List<String> list = Arrays.asList(new String[]{"nonnull", "null", null});
+    List<String> list = Arrays.asList(new String[] {"nonnull", "null", null});
     final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInStringList(
         list);
     fooReq.fire(new Receiver<Void>() {
@@ -1035,6 +1048,22 @@
     });
   }
 
+  /**
+   * Tests a message consisting only of operations, with no invocations.
+   */
+  public void testOperationOnlyMessage() {
+    delayTestFinish(DELAY_TEST_FINISH);
+    RequestContext ctx = simpleFooRequest();
+    SimpleFooProxy proxy = ctx.create(SimpleFooProxy.class);
+    proxy.setUserName("GWT");
+    ctx.fire(new Receiver<Void>() {
+      @Override
+      public void onSuccess(Void response) {
+        finishTestAndReset();
+      }
+    });
+  }
+
   public void testPersistAllValueTypes() {
     delayTestFinish(DELAY_TEST_FINISH);