1. Removed the ServerType annotation that is not currently used.
2. Re-introduced an Enum type that specifies the domain class, domain method
and the return type of objects returned on invoking the domain method. This
enum type will be generated by some JPA-aware tool.
Patch by: amitmanjhi
Review by: rjrjr (desk review)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7773 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 dd27321..71ff490 100644
--- a/bikeshed/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java
+++ b/bikeshed/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java
@@ -21,6 +21,7 @@
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.sample.expenses.shared.ExpenseRequestFactory.ServerSideOperation;
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.SyncRequest;
import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
@@ -124,7 +125,7 @@
// TODO: Fix the className for this request
builder.setRequestData(ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
- "", "sync", null, requestData.toString())));
+ ServerSideOperation.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/ServerType.java b/bikeshed/src/com/google/gwt/requestfactory/shared/ServerType.java
deleted file mode 100644
index cc61e6e..0000000
--- a/bikeshed/src/com/google/gwt/requestfactory/shared/ServerType.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.shared;
-
-/**
- * Identifies the server domain class represented by an {@link EntityRef}.
- */
-public @interface ServerType {
-
- Class<?> value();
-
-}
diff --git a/bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java b/bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java
index 866361e..0447be6 100644
--- a/bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java
+++ b/bikeshed/src/com/google/gwt/requestfactory/shared/impl/RequestDataManager.java
@@ -15,20 +15,22 @@
*/
package com.google.gwt.requestfactory.shared.impl;
+import com.google.gwt.sample.expenses.shared.ExpenseRequestFactory.ServerSideOperation;
+
import java.util.HashMap;
import java.util.Map;
/**
- * An utitlity class to manage the encoding and decoding of parameters and
+ * An utility class to manage the encoding and decoding of parameters and
* methodNames.
*
* TODO: add appropriate unit tests.
*/
public class RequestDataManager {
- public static final String CLASS_TOKEN = "className";
public static final String CONTENT_TOKEN = "contentData";
public static final String METHOD_TOKEN = "methodName";
+ public static final String OPERATION_TOKEN = "operation";
public static final String PARAM_TOKEN = "param";
public static Object[] getObjectsFromParameterMap(
@@ -46,11 +48,10 @@
* Returns the string that encodes the request data.
*
*/
- public static Map<String, String> getRequestMap(String className,
- String methodName, Object values[], String content) {
+ public static Map<String, String> getRequestMap(
+ ServerSideOperation operation, Object values[], String content) {
Map<String, String> requestMap = new HashMap<String, String>();
- requestMap.put(CLASS_TOKEN, className);
- requestMap.put(METHOD_TOKEN, methodName);
+ requestMap.put(OPERATION_TOKEN, operation.name());
if (values != null) {
for (int i = 0; i < values.length; i++) {
Object value = values[i];
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 c9e8caa..3012914 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gen/EmployeeRequestImpl.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gen/EmployeeRequestImpl.java
@@ -25,7 +25,7 @@
import com.google.gwt.valuestore.shared.ValueStore;
/**
- * "Code generated" implementation of {ExpenseRequestFactory.EmployeeRequest}
+ * "Code generated" implementation of {ExpenseRequestFactory.EmployeeRequest}.
* <p>
* IRL this will be generated as a side effect of a call to
* GWT.create(ExpenseRequestFactory.class)
@@ -59,7 +59,7 @@
return new Request() {
public String getRequestData() {
return ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
- "Employee", "findAllEmployees", null, null));
+ ExpenseRequestFactory.ServerSideOperation.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 50f4bd2..07642e3 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gen/ReportRequestImpl.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gen/ReportRequestImpl.java
@@ -27,7 +27,7 @@
import com.google.gwt.valuestore.shared.ValueStore;
/**
- * "Code generated" implementation of {ExpenseRequestFactory.ReportRequest}
+ * "Code generated" implementation of {ExpenseRequestFactory.ReportRequest}.
* <p>
* IRL this will be generated as a side effect of a call to
* GWT.create(ExpenseRequestFactory.class)
@@ -60,7 +60,8 @@
return new Request() {
public String getRequestData() {
return ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
- "Report", "findAllReports", null, null));
+ ExpenseRequestFactory.ServerSideOperation.FIND_ALL_REPORTS, null,
+ null));
}
};
@@ -71,7 +72,8 @@
return new Request() {
public String getRequestData() {
return ClientRequestObject.getRequestString(RequestDataManager.getRequestMap(
- "Report", "findReportsByEmployee", new Object[] {id.get()}, null));
+ ExpenseRequestFactory.ServerSideOperation.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 6263b2c..1c5c728 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/server/ExpensesDataServlet.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/server/ExpensesDataServlet.java
@@ -19,6 +19,7 @@
import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
import com.google.gwt.sample.expenses.server.domain.Report;
import com.google.gwt.sample.expenses.server.domain.Storage;
+import com.google.gwt.sample.expenses.shared.ExpenseRequestFactory.ServerSideOperation;
import com.google.gwt.sample.expenses.shared.ReportKey;
import com.google.gwt.valuestore.shared.Property;
@@ -61,52 +62,48 @@
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
- String className = null;
- String methodName = null;
+ ServerSideOperation operation = null;
try {
response.setStatus(HttpServletResponse.SC_OK);
JSONObject topLevelJsonObject = new JSONObject(getContent(request));
- className = topLevelJsonObject.getString(RequestDataManager.CLASS_TOKEN);
- methodName = topLevelJsonObject.getString(RequestDataManager.METHOD_TOKEN);
+ operation = getOperationFromName(topLevelJsonObject.getString(RequestDataManager.OPERATION_TOKEN));
PrintWriter writer = response.getWriter();
- if (methodName.equals("sync")) {
- sync(topLevelJsonObject.getString(RequestDataManager.CONTENT_TOKEN),
- writer);
- } else {
- Class<?> classOperation = Class.forName("com.google.gwt.sample.expenses.server.domain."
- + className);
- Method methodOperation = null;
- // TODO: check if method names must be unique in a class.
- for (Method method : classOperation.getDeclaredMethods()) {
- if (method.getName().equals(methodName)) {
- methodOperation = method;
- break;
+ switch (operation) {
+ case SYNC:
+ sync(topLevelJsonObject.getString(RequestDataManager.CONTENT_TOKEN),
+ writer);
+ break;
+ case FIND_ALL_EMPLOYEES:
+ case FIND_ALL_REPORTS:
+ case FIND_EMPLOYEE:
+ case FIND_REPORTS_BY_EMPLOYEE:
+ Class<?> domainClass = Class.forName(operation.getDomainClassName());
+ Method domainMethod = domainClass.getMethod(
+ operation.getDomainMethodName(), operation.getParameterTypes());
+ if (!Modifier.isStatic(domainMethod.getModifiers())) {
+ throw new IllegalArgumentException("the " + domainMethod.getName()
+ + " is not static");
}
- }
- if (methodOperation == null) {
- throw new IllegalArgumentException("unable to find " + methodName
- + " 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());
+ Object args[] = RequestDataManager.getObjectsFromParameterMap(
+ getParameterMap(topLevelJsonObject),
+ domainMethod.getParameterTypes());
+ Object resultList = domainMethod.invoke(null, args);
+ if (!(resultList instanceof List)) {
+ throw new IllegalArgumentException("return value not a list "
+ + resultList);
+ }
+ JSONArray jsonArray = getJsonArray((List<?>) resultList,
+ operation.getReturnType());
+ writer.print(jsonArray.toString());
+ break;
+ default:
+ throw new IllegalArgumentException("Unknow operation " + operation);
}
writer.flush();
// TODO: clean exception handling code below.
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("unable to load the class: "
- + className);
+ + operation.getDomainClassName());
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
} catch (InvocationTargetException e) {
@@ -136,24 +133,16 @@
* Converts the returnValue of a 'get' method to a JSONArray.
*
* @param resultObject object returned by a 'get' method, must be of type
- * List<? extends Entity>
+ * List<?>
* @return the JSONArray
*/
- private JSONArray getJsonArray(List<?> resultList)
- throws ClassNotFoundException, SecurityException, JSONException,
+ private JSONArray getJsonArray(List<?> resultList,
+ Class<? extends EntityKey<?>> entityKeyClass) throws JSONException,
NoSuchMethodException, IllegalAccessException, InvocationTargetException {
JSONArray jsonArray = new JSONArray();
if (resultList.size() == 0) {
return jsonArray;
}
- Object firstElement = resultList.get(0);
- Class<?> entityClass = firstElement.getClass();
-
- // TODO This brittle mapping from server name to client name is why we need
- // the custom RequestFactory interface to serve as the config
- Class<?> entityKeyClass = Class.forName("com.google.gwt.sample.expenses.shared."
- + entityClass.getSimpleName() + "Key");
-
EntityKey<?> key = (EntityKey<?>) entityKeyClass.getMethod("get").invoke(
null);
for (Object entityElement : resultList) {
@@ -188,6 +177,15 @@
return methodName.toString();
}
+ private ServerSideOperation getOperationFromName(String operationName) {
+ for (ServerSideOperation operation : ServerSideOperation.values()) {
+ if (operation.name().equals(operationName)) {
+ return operation;
+ }
+ }
+ throw new IllegalArgumentException("Unknown operation " + operationName);
+ }
+
/**
* @param jsonObject
* @return
@@ -196,7 +194,7 @@
private Map<String, String> getParameterMap(JSONObject jsonObject)
throws JSONException {
Map<String, String> parameterMap = new HashMap<String, String>();
- Iterator keys = jsonObject.keys();
+ Iterator<?> keys = jsonObject.keys();
while (keys.hasNext()) {
String key = keys.next().toString();
if (key.startsWith(RequestDataManager.PARAM_TOKEN)) {
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/server/domain/Report.java b/bikeshed/src/com/google/gwt/sample/expenses/server/domain/Report.java
index a87c719..1a3dbf1 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/server/domain/Report.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/server/domain/Report.java
@@ -35,7 +35,7 @@
return Storage.INSTANCE.findReport(id);
}
- public static List<Report> findReportsByEmployee(long id) {
+ public static List<Report> findReportsByEmployee(Long id) {
return Storage.INSTANCE.findReportsByEmployee(id);
}
private final Long id;
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/shared/EmployeeKey.java b/bikeshed/src/com/google/gwt/sample/expenses/shared/EmployeeKey.java
index de1264d..a7de62d 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/shared/EmployeeKey.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/shared/EmployeeKey.java
@@ -18,7 +18,6 @@
import com.google.gwt.requestfactory.shared.EntityKey;
import com.google.gwt.requestfactory.shared.Id;
import com.google.gwt.requestfactory.shared.LongString;
-import com.google.gwt.requestfactory.shared.ServerType;
import com.google.gwt.requestfactory.shared.Version;
import com.google.gwt.valuestore.shared.Property;
@@ -33,7 +32,6 @@
* IRL this class will be generated by a JPA-savvy tool run before
* compilation.
*/
-@ServerType(com.google.gwt.sample.expenses.server.domain.Employee.class)
public class EmployeeKey implements EntityKey<EmployeeKey> {
private static EmployeeKey instance;
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/shared/ExpenseRequestFactory.java b/bikeshed/src/com/google/gwt/sample/expenses/shared/ExpenseRequestFactory.java
index ac66d3f..1f36972 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/shared/ExpenseRequestFactory.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/shared/ExpenseRequestFactory.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.sample.expenses.shared;
+import com.google.gwt.requestfactory.shared.EntityKey;
import com.google.gwt.requestfactory.shared.EntityListRequest;
import com.google.gwt.requestfactory.shared.LongString;
import com.google.gwt.requestfactory.shared.RequestFactory;
@@ -59,6 +60,73 @@
}
/**
+ * Represents the server side operation to be carried out. This enum will be
+ * generated by the JPA-aware tool.
+ *
+ */
+ public enum ServerSideOperation {
+ FIND_ALL_EMPLOYEES("com.google.gwt.sample.expenses.server.domain.Employee",
+ "findAllEmployees", null,
+ com.google.gwt.sample.expenses.shared.EmployeeKey.class), /* */
+ FIND_ALL_REPORTS("com.google.gwt.sample.expenses.server.domain.Report",
+ "findAllReports", null,
+ com.google.gwt.sample.expenses.shared.ReportKey.class), /* */
+ FIND_EMPLOYEE("com.google.gwt.sample.expenses.server.domain.Employee",
+ "findEmployee", new Class[] {java.lang.Long.class},
+ com.google.gwt.sample.expenses.shared.EmployeeKey.class), /* */
+ FIND_REPORTS_BY_EMPLOYEE(
+ "com.google.gwt.sample.expenses.server.domain.Report",
+ "findReportsByEmployee", new Class[] {java.lang.Long.class},
+ com.google.gwt.sample.expenses.shared.ReportKey.class), /* */
+ SYNC("", "", null, null);
+
+ /**
+ * the server side domain class.
+ */
+ private final String domainClassName;
+
+ /**
+ * the methodName of the domain class that is to be invoked.
+ */
+ private final String domainMethodName;
+
+ /**
+ * the parameterTypes of the parameters the domain method requires.
+ */
+ private final Class<?>[] parameterTypes;
+
+ /**
+ * for "READ" methods, the methods return a List. This class denotes the types
+ * of the elements of the list.
+ */
+ private final Class<? extends EntityKey<?>> returnType;
+
+ private ServerSideOperation(String domainClassName, String domainMethodName,
+ Class<?> parameterTypes[], Class<? extends EntityKey<?>> entryReturnType) {
+ this.domainClassName = domainClassName;
+ this.domainMethodName = domainMethodName;
+ this.parameterTypes = parameterTypes;
+ this.returnType = entryReturnType;
+ }
+
+ public String getDomainClassName() {
+ return domainClassName;
+ }
+
+ public String getDomainMethodName() {
+ return domainMethodName;
+ }
+
+ public Class<?>[] getParameterTypes() {
+ return parameterTypes;
+ }
+
+ public Class<? extends EntityKey<?>> getReturnType() {
+ return returnType;
+ }
+ }
+
+ /**
* @return a request selector
*/
EmployeeRequest employeeRequest();
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/shared/ReportKey.java b/bikeshed/src/com/google/gwt/sample/expenses/shared/ReportKey.java
index d78e991..202b78a 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/shared/ReportKey.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/shared/ReportKey.java
@@ -18,7 +18,6 @@
import com.google.gwt.requestfactory.shared.EntityKey;
import com.google.gwt.requestfactory.shared.Id;
import com.google.gwt.requestfactory.shared.LongString;
-import com.google.gwt.requestfactory.shared.ServerType;
import com.google.gwt.requestfactory.shared.Version;
import com.google.gwt.valuestore.shared.Property;
@@ -34,7 +33,6 @@
* IRL this class will be generated by a JPA-savvy tool run before
* compilation.
*/
-@ServerType(com.google.gwt.sample.expenses.server.domain.Report.class)
public class ReportKey implements EntityKey<ReportKey> {
private static ReportKey instance;