1. Updates all requests to use POST instead of GET.
2. Use JSON to encode requests instead of a custom solution.
Patch by: amitmanjhi
Review by: rjrjr (desk review and TBR)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7762 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/requestfactory/client/gen/ClientRequestObject.java b/bikeshed/src/com/google/gwt/requestfactory/client/gen/ClientRequestObject.java
new file mode 100644
index 0000000..6f247f6
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/requestfactory/client/gen/ClientRequestObject.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed 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 com.google.gwt.requestfactory.client.gen;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+import java.util.Map;
+
+/**
+ * A convenience class to convert a Map<String, String> to a Json string on the
+ * client side.
+ */
+public class ClientRequestObject {
+
+ public static String getRequestString(Map<String, String> requestData) {
+ ClientRequestObject requestObject = new ClientRequestObject();
+ requestObject.init();
+ for (String key : requestData.keySet()) {
+ requestObject.put(key, requestData.get(key));
+ }
+ return requestObject.toJsonString();
+ }
+
+ private JavaScriptObject map;
+
+ ClientRequestObject() {
+ init();
+ }
+
+ private native void init()/*-{
+ this.@com.google.gwt.requestfactory.client.gen.ClientRequestObject::map = {};
+ }-*/;
+
+ private native void put(String key, String value)/*-{
+ this.@com.google.gwt.requestfactory.client.gen.ClientRequestObject::map[key] = value;
+ }-*/;
+
+ private native String toJsonString()/*-{
+ return JSON.stringify(this.@com.google.gwt.requestfactory.client.gen.ClientRequestObject::map);
+ }-*/;
+}
diff --git a/bikeshed/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java b/bikeshed/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java
index 3cc12b4..d8f3122 100644
--- a/bikeshed/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java
+++ b/bikeshed/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java
@@ -20,8 +20,10 @@
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
+import com.google.gwt.requestfactory.client.gen.ClientRequestObject;
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.SyncRequest;
+import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
import com.google.gwt.sample.expenses.gen.MethodName;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasValueList;
@@ -39,7 +41,7 @@
*/
public class RequestFactoryJsonImpl implements RequestFactory,
RequestFactory.Service {
-
+
private final ValueStore valueStore = new ValueStore() {
public void addValidation() {
@@ -59,13 +61,13 @@
T propertyOwner, Set<Property<T, ?>> properties) {
throw new UnsupportedOperationException();
}
-
+
};
- @SuppressWarnings("deprecation")
public void fire(final RequestObject requestObject) {
- RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
- requestObject.getRequestUrl());
+ RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
+ RequestFactory.URL);
+ builder.setRequestData(requestObject.getRequestData());
builder.setCallback(new RequestCallback() {
public void onError(Request request, Throwable exception) {
@@ -106,7 +108,7 @@
public void fire() {
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
- "/expenses/data?methodName=" + MethodName.SYNC.name());
+ "/expenses/data");
StringBuilder requestData = new StringBuilder("[");
boolean first = true;
@@ -121,7 +123,8 @@
}
requestData.append("]");
- builder.setRequestData(requestData.toString());
+ builder.setRequestData(ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
+ MethodName.SYNC, null, requestData.toString())));
builder.setCallback(new RequestCallback() {
public void onError(Request request, Throwable exception) {
diff --git a/bikeshed/src/com/google/gwt/requestfactory/shared/RequestFactory.java b/bikeshed/src/com/google/gwt/requestfactory/shared/RequestFactory.java
index ac379ef..b582bd8 100644
--- a/bikeshed/src/com/google/gwt/requestfactory/shared/RequestFactory.java
+++ b/bikeshed/src/com/google/gwt/requestfactory/shared/RequestFactory.java
@@ -25,18 +25,15 @@
*/
public interface RequestFactory {
+ String URL = "/expenses/data";
+
/**
* Implemented by the request objects created by this factory.
*/
interface RequestObject {
void fire();
- String getRequestData(String data);
-
- /**
- * @deprecated Here only until we can move everything into the post data
- */
- String getRequestUrl();
+ String getRequestData();
void handleResponseText(String responseText);
}
diff --git a/bikeshed/src/com/google/gwt/requestfactory/shared/impl/UrlParameterManager.java b/bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java
similarity index 61%
rename from bikeshed/src/com/google/gwt/requestfactory/shared/impl/UrlParameterManager.java
rename to bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java
index fbec5c8..044f522 100644
--- a/bikeshed/src/com/google/gwt/requestfactory/shared/impl/UrlParameterManager.java
+++ b/bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java
@@ -15,19 +15,25 @@
*/
package com.google.gwt.requestfactory.shared.impl;
+import com.google.gwt.sample.expenses.gen.MethodName;
+
+import java.util.HashMap;
import java.util.Map;
/**
- * An utitlity class to manage the encoding and decoding of parameters.
- *
+ * An utitlity class to manage the encoding and decoding of parameters and
+ * methodNames.
+ *
* TODO: add appropriate unit tests.
*/
-public class UrlParameterManager {
+public class RequestDataManager {
- private static final String TOKEN = "param";
+ public static final String CONTENT_TOKEN = "contentData";
+ public static final String METHOD_TOKEN = "methodName";
+ public static final String PARAM_TOKEN = "param";
- public static Object[] getObjectsFromFragment(
- Map<String, String[]> parameterMap, Class<?> parameterClasses[]) {
+ public static Object[] getObjectsFromParameterMap(
+ Map<String, String> parameterMap, Class<?> parameterClasses[]) {
assert parameterClasses != null;
Object args[] = new Object[parameterClasses.length];
for (int i = 0; i < parameterClasses.length; i++) {
@@ -38,23 +44,23 @@
}
/**
- * Returns the string that encodes the values. The string has a leading &.
+ * Returns the string that encodes the request data.
*
- * @param values
- * @return
*/
- public static String getUrlFragment(Object values[]) {
- assert values != null;
- StringBuffer fragment = new StringBuffer();
- for (int i = 0; i < values.length; i++) {
- Object value = values[i];
- fragment.append("&");
- fragment.append(TOKEN);
- fragment.append(i);
- fragment.append("=");
- fragment.append(value.toString());
+ public static Map<String, String> getRequestMap(MethodName methodName,
+ Object values[], String content) {
+ Map<String, String> requestMap = new HashMap<String, String>();
+ requestMap.put(METHOD_TOKEN, methodName.name());
+ if (values != null) {
+ for (int i = 0; i < values.length; i++) {
+ Object value = values[i];
+ requestMap.put(PARAM_TOKEN + i, value.toString());
+ }
}
- return fragment.toString();
+ if (content != null) {
+ requestMap.put(CONTENT_TOKEN, content);
+ }
+ return requestMap;
}
/**
@@ -62,10 +68,7 @@
*
*/
private static Object encodeParameterValue(String parameterType,
- String parameterValues[]) {
- assert parameterValues != null;
- assert parameterValues.length == 1;
- String parameterValue = parameterValues[0];
+ String parameterValue) {
if ("java.lang.String".equals(parameterType)) {
return parameterValue;
}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gen/EmployeeRequestImpl.java b/bikeshed/src/com/google/gwt/sample/expenses/gen/EmployeeRequestImpl.java
index 247e48a..fc4986b 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gen/EmployeeRequestImpl.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gen/EmployeeRequestImpl.java
@@ -15,9 +15,11 @@
*/
package com.google.gwt.sample.expenses.gen;
+import com.google.gwt.requestfactory.client.gen.ClientRequestObject;
import com.google.gwt.requestfactory.client.impl.AbstractListJsonRequestObject;
import com.google.gwt.requestfactory.shared.EntityListRequest;
import com.google.gwt.requestfactory.shared.RequestFactory.Service;
+import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
import com.google.gwt.sample.expenses.shared.EmployeeKey;
import com.google.gwt.sample.expenses.shared.ExpenseRequestFactory;
import com.google.gwt.valuestore.shared.ValueStore;
@@ -55,15 +57,9 @@
public EntityListRequest<EmployeeKey> findAllEmployees() {
return new Request() {
- public String getRequestData(String data) {
- // TODO Dear Amit: your code here
- throw new UnsupportedOperationException();
- }
-
- @SuppressWarnings("deprecation")
- public String getRequestUrl() {
- return "/expenses/data?methodName="
- + MethodName.FIND_ALL_EMPLOYEES.name();
+ public String getRequestData() {
+ return ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(MethodName.FIND_ALL_EMPLOYEES,
+ null, null));
}
};
}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gen/ReportRequestImpl.java b/bikeshed/src/com/google/gwt/sample/expenses/gen/ReportRequestImpl.java
index cbb43c0..fc7d872 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gen/ReportRequestImpl.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gen/ReportRequestImpl.java
@@ -15,10 +15,11 @@
*/
package com.google.gwt.sample.expenses.gen;
+import com.google.gwt.requestfactory.client.gen.ClientRequestObject;
import com.google.gwt.requestfactory.client.impl.AbstractListJsonRequestObject;
import com.google.gwt.requestfactory.shared.EntityListRequest;
import com.google.gwt.requestfactory.shared.RequestFactory.Service;
-import com.google.gwt.requestfactory.shared.impl.UrlParameterManager;
+import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
import com.google.gwt.sample.expenses.shared.EmployeeKey;
import com.google.gwt.sample.expenses.shared.ExpenseRequestFactory;
import com.google.gwt.sample.expenses.shared.ReportKey;
@@ -57,32 +58,20 @@
public EntityListRequest<ReportKey> findAllReports() {
return new Request() {
- public String getRequestData(String data) {
- // TODO Dear Amit: your code here
- throw new UnsupportedOperationException();
+ public String getRequestData() {
+ return ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
+ MethodName.FIND_ALL_REPORTS, null, null));
}
- @SuppressWarnings("deprecation")
- public String getRequestUrl() {
- return "/expenses/data?methodName="
- + MethodName.FIND_ALL_REPORTS.name();
- }
};
};
public EntityListRequest<ReportKey> findReportsByEmployee(
final ValueRef<EmployeeKey, String> id) {
return new Request() {
- public String getRequestData(String data) {
- // TODO Dear Amit: your code here
- throw new UnsupportedOperationException();
- }
-
- @SuppressWarnings("deprecation")
- public String getRequestUrl() {
- return "/expenses/data?methodName="
- + MethodName.FIND_REPORTS_BY_EMPLOYEE.name()
- + UrlParameterManager.getUrlFragment(new Object[] {id.get()});
+ public String getRequestData() {
+ return ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
+ MethodName.FIND_REPORTS_BY_EMPLOYEE, new Object[] {id.get()}, null));
}
};
}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/server/ExpensesDataServlet.java b/bikeshed/src/com/google/gwt/sample/expenses/server/ExpensesDataServlet.java
index fcc185b..ace0c01 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/server/ExpensesDataServlet.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/server/ExpensesDataServlet.java
@@ -16,7 +16,7 @@
package com.google.gwt.sample.expenses.server;
import com.google.gwt.requestfactory.shared.EntityKey;
-import com.google.gwt.requestfactory.shared.impl.UrlParameterManager;
+import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
import com.google.gwt.sample.expenses.gen.MethodName;
import com.google.gwt.sample.expenses.server.domain.Report;
import com.google.gwt.sample.expenses.server.domain.Storage;
@@ -33,7 +33,9 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -56,48 +58,61 @@
}
}
- @SuppressWarnings("unchecked")
@Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
- response.setStatus(HttpServletResponse.SC_OK);
- PrintWriter writer = response.getWriter();
- MethodName operation = getMethodName(request.getParameter("methodName"));
+ MethodName methodName = null;
try {
- Class<?> classOperation = Class.forName("com.google.gwt.sample.expenses.server.domain."
- + operation.getClassName());
- Method methodOperation = null;
- // TODO: check if method names must be unique in a class.
- for (Method method : classOperation.getDeclaredMethods()) {
- if (method.getName().equals(operation.getMethodName())) {
- methodOperation = method;
+ response.setStatus(HttpServletResponse.SC_OK);
+ JSONObject topLevelJsonObject = new JSONObject(getContent(request));
+ methodName = getMethodName(topLevelJsonObject.getString(RequestDataManager.METHOD_TOKEN));
+ PrintWriter writer = response.getWriter();
+ switch (methodName) {
+ case FIND_ALL_EMPLOYEES:
+ case FIND_ALL_REPORTS:
+ case FIND_EMPLOYEE:
+ case FIND_REPORTS_BY_EMPLOYEE:
+ Class<?> classOperation = Class.forName("com.google.gwt.sample.expenses.server.domain."
+ + methodName.getClassName());
+ Method methodOperation = null;
+ // TODO: check if method names must be unique in a class.
+ for (Method method : classOperation.getDeclaredMethods()) {
+ if (method.getName().equals(methodName.getMethodName())) {
+ methodOperation = method;
+ break;
+ }
+ }
+ if (methodOperation == null) {
+ throw new IllegalArgumentException("unable to find "
+ + methodName.getMethodName() + " in " + classOperation);
+ }
+ if (!Modifier.isStatic(methodOperation.getModifiers())) {
+ throw new IllegalArgumentException("the "
+ + methodOperation.getName() + " is not static");
+ }
+ Object args[] = RequestDataManager.getObjectsFromParameterMap(
+ getParameterMap(topLevelJsonObject), methodOperation.getParameterTypes());
+ Object resultList = methodOperation.invoke(null, args);
+ if (!(resultList instanceof List)) {
+ throw new IllegalArgumentException("return value not a list "
+ + resultList);
+ }
+ JSONArray jsonArray = getJsonArray((List<?>) resultList);
+ writer.print(jsonArray.toString());
break;
- }
+ case SYNC:
+ sync(topLevelJsonObject.getString(RequestDataManager.CONTENT_TOKEN), writer);
+ break;
+ default:
+ System.err.println("POST: unknown method " + methodName);
+ break;
}
- if (methodOperation == null) {
- throw new IllegalArgumentException("unable to find "
- + operation.getMethodName() + " in " + classOperation);
- }
- if (!Modifier.isStatic(methodOperation.getModifiers())) {
- throw new IllegalArgumentException("the " + methodOperation.getName()
- + " is not static");
- }
- Map<String, String[]> parameterMap = request.getParameterMap();
- Object args[] = UrlParameterManager.getObjectsFromFragment(parameterMap,
- methodOperation.getParameterTypes());
- Object resultList = methodOperation.invoke(null, args);
- if (!(resultList instanceof List)) {
- throw new IllegalArgumentException("return value not a list "
- + resultList);
- }
- JSONArray jsonArray = getJsonArray((List<?>) resultList);
- writer.print(jsonArray.toString());
writer.flush();
// TODO: clean exception handling code below.
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("unable to load the class: "
- + operation);
+ + methodName);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
} catch (InvocationTargetException e) {
@@ -108,25 +123,19 @@
throw new IllegalArgumentException(e);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e);
- }
+ }
}
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws IOException {
-
- response.setStatus(HttpServletResponse.SC_OK);
- MethodName methodName = getMethodName(request.getParameter("methodName"));
- PrintWriter writer = response.getWriter();
- switch (methodName) {
- case SYNC:
- sync(request, writer);
- break;
- default:
- System.err.println("POST: unknown method " + methodName);
- break;
+ private String getContent(HttpServletRequest request) throws IOException {
+ int contentLength = request.getContentLength();
+ byte contentBytes[] = new byte[contentLength];
+ BufferedInputStream bis = new BufferedInputStream(request.getInputStream());
+ int readBytes = 0;
+ while (bis.read(contentBytes, readBytes, contentLength - readBytes) > 0) {
+ // read the contents
}
- writer.flush();
+ // TODO: encoding issues?
+ return new String(contentBytes);
}
/**
@@ -198,6 +207,23 @@
}
/**
+ * @param jsonObject
+ * @return
+ * @throws JSONException
+ */
+ private Map<String, String> getParameterMap(JSONObject jsonObject) throws JSONException {
+ Map<String, String> parameterMap = new HashMap<String, String>();
+ Iterator keys = jsonObject.keys();
+ while (keys.hasNext()) {
+ String key = keys.next().toString();
+ if (key.startsWith(RequestDataManager.PARAM_TOKEN)) {
+ parameterMap.put(key, jsonObject.getString(key));
+ }
+ }
+ return parameterMap;
+ }
+
+ /**
* @param entityElement
* @param property
* @return
@@ -232,21 +258,10 @@
}
/**
- * @param request
- * @param writer
* @throws IOException
*/
- private void sync(HttpServletRequest request, PrintWriter writer)
- throws IOException {
- int contentLength = request.getContentLength();
- byte contentBytes[] = new byte[contentLength];
- BufferedInputStream bis = new BufferedInputStream(request.getInputStream());
- int readBytes = 0;
- while (bis.read(contentBytes, readBytes, contentLength - readBytes) > 0) {
- // read the contents
- }
- // TODO: encoding issues?
- String content = new String(contentBytes);
+ private void sync(String content, PrintWriter writer) throws IOException {
+
try {
JSONArray reportArray = new JSONArray(content);
int length = reportArray.length();