Thanks for the heads up Cassie!

I'm unavoidably tied up until mid friday, but i'll start banging on it as soon as possible. First impression is very good though, way of dealing with it looks sound and practical, and should be relatively trivial to add on the php side too.

Good job!

Ps, just a thought that occurred to me: Since the spec doesn't yet mention batching using the json format .. would we dare suggesting adding it to the restful api properly or do we hide it in the not- documented cellar and save the big coming out party for 0.9?

        -- Chris

On Jun 18, 2008, at 9:43 PM, Cassie wrote:

Hey Chris and other php guys - I just wanted to alert you to the json
batching stuff I wrote for the java restful server. This batching isn't in the spec (the spec has some crazy multi part thing that is super atom pub specific) so at this point it is just an extension so that the opensocial js
apis can work better (because not batching is a regression).

Lemme know what you think of the format - its pretty similar to what we had for the old json wire format. Once we clean this up we can propose it to the
restful spec list as an alternative to the atomy batching.

All input welcome!

- Cassie


On Wed, Jun 18, 2008 at 12:39 PM, <[EMAIL PROTECTED]> wrote:

Author: doll
Date: Wed Jun 18 12:39:54 2008
New Revision: 669268

URL: http://svn.apache.org/viewvc?rev=669268&view=rev
Log:
The dataservice rest impl now supports a jsonBatch format. This batch
format can now be optionally turned on in the restfulcontainer.js code.

(As soon as php implements the batching stuff then we can remove the flag
and always use batching)



Added:

incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/RequestItemTest.java

incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulBatchTest.java
Modified:
incubator/shindig/trunk/features/opensocial-current/ restfulcontainer.js

incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/DataServiceServlet.java

incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/RequestItem.java

incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/DataServiceServletTest.java

incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulJsonPeopleTest.java

Modified:
incubator/shindig/trunk/features/opensocial-current/ restfulcontainer.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-current/restfulcontainer.js?rev=669268&r1=669267&r2=669268&view=diff

= = = = = = = = = ===================================================================== --- incubator/shindig/trunk/features/opensocial-current/ restfulcontainer.js
(original)
+++ incubator/shindig/trunk/features/opensocial-current/ restfulcontainer.js
Wed Jun 18 12:39:54 2008
@@ -38,6 +38,8 @@
 this.baseUrl_ = baseUrl;

 this.securityToken_ = shindig.auth.getSecurityToken();
+
+  this.useBatching_ = false;
};
RestfulContainer.inherits(opensocial.Container);

@@ -94,7 +96,6 @@
   var url = requestObject.request.url;
   var separator = url.indexOf("?") != -1 ? "&" : "?";

-    // TODO: Use batching instead of doing this one by one
   gadgets.io.makeNonProxiedRequest(
       baseUrl + url + separator + "st=" + st,
       function(result) {
@@ -115,8 +116,61 @@
 }

// may need multiple urls for one response but lets ignore that for now
-  for (var i = 0; i < totalRequests; i++) {
-    makeProxiedRequest(requestObjects[i], this.baseUrl_,
this.securityToken_);
+  // TODO: Once both the php and java code decide on and implement
batching
+  // the non-batching code should be deleted
+  if (!this.useBatching_) {
+    for (var i = 0; i < totalRequests; i++) {
+      makeProxiedRequest(requestObjects[i], this.baseUrl_,
this.securityToken_);
+    }
+
+  } else {
+    var jsonBatchData = {};
+
+    for (var j = 0; j < totalRequests; j++) {
+      var requestObject = requestObjects[j];
+
+ jsonBatchData[requestObject.key] = {url : requestObject.request.url,
+        method : requestObject.request.method};
+      if (requestObject.request.postData) {
+        jsonBatchData[requestObject.key].parameters =
requestObject.request.postData;
+      }
+    }
+
+    // This is slightly different than jsonContainer
+    var sendResponse = function(result) {
+      result = result.data;
+
+      if (!result || result['error']) {
+        callback(new opensocial.DataResponse({}, true));
+        return;
+      }
+
+      var responses = result['responses'] || [];
+      var globalError = false;
+
+      var responseMap = {};
+
+      for (var k = 0; k < requestObjects.length; k++) {
+        var request = requestObjects[k];
+        var response = responses[request.key];
+
+        var rawData = response['response'];
+        var error = response['error'];
+        var errorMessage = response['errorMessage'];
+
+        var processedData = request.request.processResponse(
+            request.request, rawData, error, errorMessage);
+        globalError = globalError || processedData.hadError();
+        responseMap[request.key] = processedData;
+      }
+
+      var dataResponse = new opensocial.DataResponse(responseMap,
globalError);
+      callback(dataResponse);
+    };
+
+    // TODO: get the jsonbatch url from the container config
+    new BatchRequest(this.baseUrl_ + "/jsonBatch",
gadgets.json.stringify(jsonBatchData),
+ sendResponse, {'st' : shindig.auth.getSecurityToken()}).send();
 }

};

Modified:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/DataServiceServlet.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/dataservice/DataServiceServlet.java?rev=669268&r1=669267&r2=669268&view=diff

= = = = = = = = = =====================================================================
---
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/DataServiceServlet.java
(original)
+++
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/DataServiceServlet.java
Wed Jun 18 12:39:54 2008
@@ -17,28 +17,31 @@
*/
package org.apache.shindig.social.dataservice;

-import com.google.inject.Inject;
-import com.google.inject.Injector;
-
-import org.apache.shindig.common.SecurityTokenDecoder;
import org.apache.shindig.common.SecurityToken;
+import org.apache.shindig.common.SecurityTokenDecoder;
import org.apache.shindig.common.SecurityTokenException;
import org.apache.shindig.common.servlet.InjectedServlet;
+import org.apache.shindig.social.ResponseItem;
import org.apache.shindig.social.opensocial.util.BeanConverter;
import org.apache.shindig.social.opensocial.util.BeanJsonConverter;
import org.apache.shindig.social.opensocial.util.BeanXmlConverter;
-import org.apache.shindig.social.ResponseItem;
+
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;

-import org.apache.commons.lang.StringUtils;
-
public class DataServiceServlet extends InjectedServlet {

 protected static final String X_HTTP_METHOD_OVERRIDE =
"X-HTTP-Method-Override";
@@ -58,6 +61,7 @@
 private Map<String, Class<? extends DataRequestHandler>> handlers;
 private BeanJsonConverter jsonConverter;
 private BeanXmlConverter xmlConverter;
+  private static final String JSON_BATCH_ROUTE = "jsonBatch";

 @Inject
 public void setHandlers(HandlerProvider handlers) {
@@ -65,8 +69,7 @@
 }

 @Inject
-  public void setSecurityTokenDecoder(SecurityTokenDecoder
-      securityTokenDecoder) {
+  public void setSecurityTokenDecoder(SecurityTokenDecoder
securityTokenDecoder) {
   this.securityTokenDecoder = securityTokenDecoder;
 }

@@ -102,12 +105,67 @@
 protected void doPost(HttpServletRequest servletRequest,
     HttpServletResponse servletResponse)
     throws ServletException, IOException {
-    String path = servletRequest.getPathInfo();
-    logger.finest("Handling restful request for " + path);
+    logger.finest("Handling restful request for " +
servletRequest.getPathInfo());

   servletRequest.setCharacterEncoding("UTF-8");
+    SecurityToken token = getSecurityToken(servletRequest);
+ BeanConverter converter = getConverterForRequest(servletRequest);

-    String route = getRouteFromParameter(path);
+    if (isBatchUrl(servletRequest)) {
+      try {
+        handleBatchRequest(servletRequest, servletResponse, token,
converter);
+      } catch (JSONException e) {
+        throw new RuntimeException("Bad batch format", e);
+      }
+    } else {
+      handleSingleRequest(servletRequest, servletResponse, token,
converter);
+    }
+  }
+
+ private void handleSingleRequest(HttpServletRequest servletRequest,
+      HttpServletResponse servletResponse, SecurityToken token,
+      BeanConverter converter) throws IOException {
+ String method = getHttpMethodFromParameter(servletRequest.getMethod(),
+        servletRequest.getParameter(X_HTTP_METHOD_OVERRIDE));
+
+    RequestItem requestItem = new RequestItem(servletRequest, token,
method);
+ ResponseItem responseItem = getResponseItem(converter, requestItem);
+
+    if (responseItem.getError() == null) {
+      PrintWriter writer = servletResponse.getWriter();
+ writer.write(converter.convertToString(responseItem.getResponse()));
+    } else {
+
servletResponse.sendError(responseItem.getError().getHttpErrorCode(),
+          responseItem.getErrorMessage());
+    }
+  }
+
+  private void handleBatchRequest(HttpServletRequest servletRequest,
+      HttpServletResponse servletResponse, SecurityToken token,
+      BeanConverter converter) throws IOException, JSONException {
+
+    JSONObject requests = new
JSONObject(servletRequest.getParameter("request"));
+    Map<String, ResponseItem> responses = Maps.newHashMap();
+
+    Iterator keys = requests.keys();
+    while (keys.hasNext()) {
+      String key = (String) keys.next();
+      String request = requests.getString(key);
+
+      RequestItem requestItem = converter.convertToObject(request,
RequestItem.class);
+      requestItem.parseUrlParamsIntoParameters();
+      requestItem.setToken(token);
+
+      responses.put(key, getResponseItem(converter, requestItem));
+    }
+
+    PrintWriter writer = servletResponse.getWriter();
+    writer.write(converter.convertToString(
+        Maps.immutableMap("error", false, "responses", responses)));
+  }
+
+  ResponseItem getResponseItem(BeanConverter converter, RequestItem
requestItem) {
+    String route = getRouteFromParameter(requestItem.getUrl());
Class<? extends DataRequestHandler> handlerClass = handlers.get(route);

   if (handlerClass == null) {
@@ -115,13 +173,12 @@
   }

   DataRequestHandler handler = injector.getInstance(handlerClass);
- BeanConverter converter = getConverterForRequest(servletRequest); - // TODO: Move all conversions out of the handler up into the servlet
layer
   handler.setConverter(converter);

- String method = getHttpMethodFromParameter(servletRequest.getMethod(),
-        servletRequest.getParameter(X_HTTP_METHOD_OVERRIDE));
+    return handler.handleMethod(requestItem);
+  }

+ SecurityToken getSecurityToken(HttpServletRequest servletRequest) {
   SecurityToken token;
   try {
     token =
securityTokenDecoder .createToken(servletRequest.getParameter(SECURITY_TOKEN_PARAM));
@@ -129,20 +186,10 @@
     throw new RuntimeException(
         "Implement error return for bad security token.");
   }
-
-    ResponseItem responseItem = handler.handleMethod(
-        new RequestItem(servletRequest, token, method));
-
-    if (responseItem.getError() == null) {
-      PrintWriter writer = servletResponse.getWriter();
- writer.write(converter.convertToString(responseItem.getResponse()));
-    } else {
-
servletResponse.sendError(responseItem.getError().getHttpErrorCode(),
-          responseItem.getErrorMessage());
-    }
+    return token;
 }

-  /*package-protected*/ BeanConverter
getConverterForRequest(HttpServletRequest servletRequest) {
+ BeanConverter getConverterForRequest(HttpServletRequest servletRequest)
{
   String formatString = servletRequest.getParameter(FORMAT_PARAM);
   if (!StringUtils.isBlank(formatString) &&
formatString.equals(ATOM_FORMAT)) {
     return xmlConverter;
@@ -150,8 +197,7 @@
   return jsonConverter;
 }

- /*package-protected*/ String getHttpMethodFromParameter(String method,
-      String overrideParameter) {
+  String getHttpMethodFromParameter(String method, String
overrideParameter) {
   if (!StringUtils.isBlank(overrideParameter)) {
     return overrideParameter;
   } else {
@@ -159,11 +205,15 @@
   }
 }

- /*package-protected*/ String getRouteFromParameter(String pathInfo) {
+  String getRouteFromParameter(String pathInfo) {
   pathInfo = pathInfo.substring(1);
   int indexOfNextPathSeparator = pathInfo.indexOf("/");
   return indexOfNextPathSeparator != -1 ?
       pathInfo.substring(0, indexOfNextPathSeparator) :
       pathInfo;
 }
+
+  boolean isBatchUrl(HttpServletRequest servletRequest) {
+    return servletRequest.getPathInfo().endsWith(JSON_BATCH_ROUTE);
+  }
}

Modified:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/RequestItem.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/dataservice/RequestItem.java?rev=669268&r1=669267&r2=669268&view=diff

= = = = = = = = = =====================================================================
---
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/RequestItem.java
(original)
+++
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ shindig/social/dataservice/RequestItem.java
Wed Jun 18 12:39:54 2008
@@ -34,6 +34,8 @@
 private Map<String, String> parameters;
 private SecurityToken token;

+  public RequestItem() { }
+
 public RequestItem(String url, Map<String, String> parameters,
SecurityToken token,
     String method) {
   this.url = url;
@@ -50,7 +52,7 @@
   Map<String, String> parameters = Maps.newHashMap();

   Enumeration names = servletRequest.getParameterNames();
-    while(names.hasMoreElements()) {
+    while (names.hasMoreElements()) {
     String name = (String) names.nextElement();
     parameters.put(name, servletRequest.getParameter(name));
   }
@@ -58,6 +60,30 @@
   return parameters;
 }

+  /*
+ * Takes any url params out of the url and puts them into the param map.
+   * Usually the servlet request code does this for us but the batch
request calls have to do it
+   * by hand.
+   */
+  public void parseUrlParamsIntoParameters() {
+    if (this.parameters == null) {
+      this.parameters = Maps.newHashMap();
+    }
+
+    String fullUrl = this.url;
+    int queryParamIndex = fullUrl.indexOf("?");
+
+    if (queryParamIndex != -1) {
+      this.url = fullUrl.substring(0, queryParamIndex);
+
+      String queryParams = fullUrl.substring(queryParamIndex + 1);
+      for (String param : queryParams.split("&")) {
+        String[] paramPieces = param.split("=", 2);
+ this.parameters.put(paramPieces[0], paramPieces.length == 2 ?
paramPieces[1] : "");
+      }
+    }
+  }
+
 public String getUrl() {
   return url;
 }

Modified:
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/DataServiceServletTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/DataServiceServletTest.java?rev=669268&r1=669267&r2=669268&view=diff

= = = = = = = = = =====================================================================
---
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/DataServiceServletTest.java
(original)
+++
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/DataServiceServletTest.java
Wed Jun 18 12:39:54 2008
@@ -147,37 +147,24 @@
 }

 public void testInvalidRoute() throws Exception {
-    req.setCharacterEncoding("UTF-8");
-    EasyMock.expect(req.getPathInfo()).andReturn("/ahhh!");
-
-    EasyMock.replay(req);
   try {
-      servlet.doPost(req, res);
+ servlet.getResponseItem(null, new RequestItem("/ahhh!", null, null,
null));
     fail("The route should not have found a valid handler.");
   } catch (RuntimeException e) {
     // Yea!
     assertEquals("No handler for route: ahhh!", e.getMessage());
   }
-    EasyMock.verify(req);
 }

 public void testSecurityTokenException() throws Exception {
-    req.setCharacterEncoding("UTF-8");
-    EasyMock.expect(req.getPathInfo()).andReturn("/" +
DataServiceServlet.APPDATA_ROUTE);
-    EasyMock.expect(req.getMethod()).andReturn("POST");
-
EasyMock .expect (req .getParameter (DataServiceServlet.X_HTTP_METHOD_OVERRIDE)).andReturn("POST");
-
EasyMock .expect (req.getParameter(DataServiceServlet.FORMAT_PARAM)).andReturn(null);
-
   String tokenString = "owner:viewer:app:container.com:foo:bar";

EasyMock .expect(req.getParameter(DataServiceServlet.SECURITY_TOKEN_PARAM))
       .andReturn(tokenString);
EasyMock.expect(tokenDecoder.createToken(tokenString)).andThrow(new
SecurityTokenException(""));

-    setupInjector();
-
-    EasyMock.replay(req, tokenDecoder, injector);
+    EasyMock.replay(req, tokenDecoder);
   try {
-      servlet.doPost(req, res);
+      servlet.getSecurityToken(req);
fail("The route should have thrown an exception due to the invalid
security token.");
   } catch (RuntimeException e) {
     // Yea!
@@ -185,7 +172,7 @@
     // instead of just throwing an exception.
     assertEquals("Implement error return for bad security token.",
e.getMessage());
   }
-    EasyMock.verify(req, tokenDecoder, injector);
+    EasyMock.verify(req, tokenDecoder);
 }

 public void testGetHttpMethodFromParameter() throws Exception {
@@ -202,6 +189,20 @@
assertEquals("path", servlet.getRouteFromParameter("/path/fun/ yes"));
 }

+  public void testIsBatchUrl() throws Exception {
+    assertBatchUrl("/jsonBatch", true);
+    assertBatchUrl("/path/to/the/jsonBatch", true);
+    assertBatchUrl("/people/normalpath", false);
+  }
+
+  private void assertBatchUrl(String url, boolean isBatch) {
+    EasyMock.expect(req.getPathInfo()).andReturn(url);
+    EasyMock.replay(req);
+    assertEquals(isBatch, servlet.isBatchUrl(req));
+    EasyMock.verify(req);
+    EasyMock.reset(req);
+  }
+
 public void testGetConverterForRequest() throws Exception {
   BeanJsonConverter json = new BeanJsonConverter();
   BeanXmlConverter xml = new BeanXmlConverter();

Added:
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/RequestItemTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/RequestItemTest.java?rev=669268&view=auto

= = = = = = = = = =====================================================================
---
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/RequestItemTest.java
(added)
+++
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/RequestItemTest.java
Wed Jun 18 12:39:54 2008
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the
License.
+ */
+package org.apache.shindig.social.dataservice;
+
+import org.apache.shindig.common.SecurityToken;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+public class RequestItemTest extends TestCase {
+
+  public void testParseUrl() throws Exception {
+    String path = "/people/john.doe/@self";
+
+    RequestItem request = new RequestItem();
+    request.setUrl(path + "?fields=huey,dewey,louie");
+
+    request.parseUrlParamsIntoParameters();
+
+    assertEquals(path, request.getUrl());
+    assertEquals("huey,dewey,louie",
request.getParameters().get("fields"));
+
+    // Try it without any params
+    request = new RequestItem();
+    request.setUrl(path);
+
+    request.parseUrlParamsIntoParameters();
+
+    assertEquals(path, request.getUrl());
+    assertEquals(null, request.getParameters().get("fields"));
+  }
+
+  public void testBasicFunctions() throws Exception {
+    String url = "url";
+    Map<String, String> params = Maps.newHashMap();
+    SecurityToken token = null;
+    String method = "method";
+ RequestItem request = new RequestItem(url, params, token, method);
+
+    assertEquals(url, request.getUrl());
+    assertEquals(params, request.getParameters());
+    assertEquals(token, request.getToken());
+    assertEquals(method, request.getMethod());
+  }
+
+}
\ No newline at end of file

Added:
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulBatchTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/RestfulBatchTest.java?rev=669268&view=auto

= = = = = = = = = =====================================================================
---
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulBatchTest.java
(added)
+++
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulBatchTest.java
Wed Jun 18 12:39:54 2008
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. The ASF licenses this file to You + * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
+ * See the License for the specific language governing permissions and + * limitations under the License. For additional information regarding + * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.shindig.social.dataservice.integration;
+
+import com.google.common.collect.Maps;
+import org.json.JSONObject;
+import org.junit.Test;
+
+import java.util.Map;
+
+public class RestfulBatchTest extends AbstractLargeRestfulTests {
+
+  /**
+   * Batch format:
+   *   POST to /jsonBatch
+   *   {request :
+   *     {friends : {url : /people/john.doe/@friends, method : GET}}
+   *     {john : {url : /people/john.doe/@self, method : GET}}
+ * {updateData : {url : /appdata/john.doe/@self/appId, method :
POST, postData : {count : 1}}}
+   *   }
+   *
+   *
+   * Expected response
+   *
+   *  {error : false,
+   *   responses : {
+   *     {friends : {response : {<friend collection>}}}
+   *     {john : {response : {<john.doe>}}}
+   *     {updateData : {response : {}}}
+   *  }
+   *
+ * Each response can possibly have .error and .errorMessage properties
as well.
+   *
+   * @throws Exception if test encounters an error
+   */
+  @Test
+  public void testGetBatchRequest() throws Exception {
+    Map<String, String> extraParams = Maps.newHashMap();
+    extraParams.put("request", "{"
+ + "friends : {url : '/people/john.doe/@friends', method : 'GET'},
"
+ + "john : {url : '/people/john.doe/@self', method : 'GET'}, "
+        + "updateData : {url : '/appdata/john.doe/@self/a', method :
'POST', parameters : {entry : {count : 1}}}"
+        + "}");
+
+    String resp = getJsonResponse("jsonBatch", "POST", extraParams);
+    JSONObject result = getJson(resp);
+
+    assertEquals(false, result.getBoolean("error"));
+
+    JSONObject jsonResponses = result.getJSONObject("responses");
+    assertEquals(3, jsonResponses.length());
+
+    // friends response
+    JSONObject jsonFriends = jsonResponses.getJSONObject("friends");
+    assertFalse(jsonFriends.has("error"));
+    assertFalse(jsonFriends.has("errorMessage"));
+
+    JSONObject jsonFriendsResponse =
jsonFriends.getJSONObject("response");
+    assertEquals(2, jsonFriendsResponse.getInt("totalResults"));
+    assertEquals(0, jsonFriendsResponse.getInt("startIndex"));
+
+    // john.doe response
+    JSONObject jsonJohn = jsonResponses.getJSONObject("john");
+    assertFalse(jsonJohn.has("error"));
+    assertFalse(jsonJohn.has("errorMessage"));
+
+ JSONObject jsonJohnResponse = jsonJohn.getJSONObject("response");
+    assertEquals("john.doe", jsonJohnResponse.getString("id"));
+    assertEquals("John Doe",
jsonJohnResponse.getJSONObject("name").getString("unstructured"));
+
+    // john.doe response
+    JSONObject jsonData = jsonResponses.getJSONObject("updateData");
+    assertFalse(jsonData.has("error"));
+    assertFalse(jsonData.has("errorMessage"));
+    assertTrue(jsonData.has("response"));
+  }
+
+}
\ No newline at end of file

Modified:
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulJsonPeopleTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/RestfulJsonPeopleTest.java?rev=669268&r1=669267&r2=669268&view=diff

= = = = = = = = = =====================================================================
---
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulJsonPeopleTest.java
(original)
+++
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ shindig/social/dataservice/integration/RestfulJsonPeopleTest.java
Wed Jun 18 12:39:54 2008
@@ -29,7 +29,6 @@
import org.apache.shindig.social.opensocial.model.Url;

import com.google.common.collect.Maps;
-import org.easymock.classextension.EasyMock;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;




Reply via email to