Revision: 8115
Author: [email protected]
Date: Wed May 12 11:38:12 2010
Log: Get data generation ready for bulk uploading
http://code.google.com/p/google-web-toolkit/source/detail?r=8115
Modified:
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/DataGenerationService.java
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/DataGenerationServiceAsync.java
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/LoadExpensesDB.java
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/server/DataGenerationServiceImpl.java
/branches/2.1/bikeshed/war/WEB-INF/web.xml
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/DataGenerationService.java
Tue May 11 10:56:00 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/DataGenerationService.java
Wed May 12 11:38:12 2010
@@ -18,6 +18,8 @@
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
+import java.util.List;
+
/**
* Generate random records.
*/
@@ -31,10 +33,11 @@
/**
* Generate reports for approximately the given number of milliseconds.
- *
- * @return the number of reports in the data store following generation
*/
- int generate(int millis);
-
- int getNumReports();
-}
+ void generate(int millis);
+
+ /**
+ * @return the number of Employees, Reports, and Expenses.
+ */
+ List<Integer> getCounts();
+}
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/DataGenerationServiceAsync.java
Tue May 11 10:56:00 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/DataGenerationServiceAsync.java
Wed May 12 11:38:12 2010
@@ -17,11 +17,13 @@
import com.google.gwt.user.client.rpc.AsyncCallback;
+import java.util.List;
+
/**
* Async counterpart of {...@link DataGenerationService}.
*/
public interface DataGenerationServiceAsync {
void delete(AsyncCallback<Void> callback);
- void generate(int millis, AsyncCallback<Integer> callback);
- void getNumReports(AsyncCallback<Integer> callback);
-}
+ void generate(int millis, AsyncCallback<Void> callback);
+ void getCounts(AsyncCallback<List<Integer>> callback);
+}
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/LoadExpensesDB.java
Tue May 11 11:18:39 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/LoadExpensesDB.java
Wed May 12 11:38:12 2010
@@ -21,10 +21,13 @@
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
+import java.util.List;
+
/**
* Entry point to create database entries for the Expenses app.
*/
@@ -32,13 +35,20 @@
private final DataGenerationServiceAsync dataService =
GWT.create(DataGenerationService.class);
- private Label generateLabel;
+ private Label statusLabel;
+ private Label numEmployeesLabel;
+ private Label numReportsLabel;
+ private Label numExpensesLabel;
private Button generateButton;
private Button deleteButton;
private TextBox amountTextBox;
public void onModuleLoad() {
- generateLabel = new Label("-- Expense Reports");
+ statusLabel = new Label("");
+ numEmployeesLabel = new Label("-- Employees");
+ numReportsLabel = new Label("-- Reports");
+ numExpensesLabel = new Label("-- Expenses");
+
generateButton = new Button("Generate Data");
deleteButton = new Button("Delete everything");
amountTextBox = new TextBox();
@@ -52,6 +62,7 @@
deleteButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
+ deleteButton.setEnabled(false);
deleteData();
}
});
@@ -59,43 +70,68 @@
RootPanel root = RootPanel.get();
root.add(generateButton);
root.add(amountTextBox);
- root.add(generateLabel);
-
- // This button deletes the entire data store -- don't expose it by
default
- // root.add(deleteButton);
-
- dataService.getNumReports(new AsyncCallback<Integer>() {
+ root.add(statusLabel);
+ root.add(numEmployeesLabel);
+ root.add(numReportsLabel);
+ root.add(numExpensesLabel);
+
+ root.add(new HTML("<br>"));
+ root.add(new HTML("<br>"));
+ root.add(new HTML("<br>"));
+ root.add(new HTML("<br>"));
+ root.add(new HTML("<br>"));
+ root.add(new HTML("<br>"));
+
+ // This button deletes the entire data store -- be careful
+ root.add(deleteButton);
+
+ updateCounts();
+ }
+
+ private void deleteData() {
+ dataService.delete(new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
+ statusLabel.setText("Deletion failed");
+ deleteButton.setEnabled(true);
+ updateCounts();
}
- public void onSuccess(Integer result) {
- generateLabel.setText("" + result + " Expense Reports");
+ public void onSuccess(Void result) {
+ statusLabel.setText("Deletion succeeded");
+ deleteButton.setEnabled(true);
+ updateCounts();
}
});
}
-
- private void deleteData() {
- dataService.delete(new AsyncCallback<Void>() {
+
+ private void updateCounts() {
+ dataService.getCounts(new AsyncCallback<List<Integer>>() {
public void onFailure(Throwable caught) {
- generateLabel.setText("Deletion failed");
+ numEmployeesLabel.setText("? Employees");
+ numReportsLabel.setText("? Reports");
+ numExpensesLabel.setText("? Expenses");
}
- public void onSuccess(Void result) {
- generateLabel.setText("Deletion succeeded");
+ public void onSuccess(List<Integer> result) {
+ numEmployeesLabel.setText("" + result.get(0) + " Employees");
+ numReportsLabel.setText("" + result.get(1) + " Reports");
+ numExpensesLabel.setText("" + result.get(2) + " Expenses");
}
});
}
private void generateData(int amount) {
- dataService.generate(amount, new AsyncCallback<Integer>() {
+ dataService.generate(amount, new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
+ statusLabel.setText("Data generation failed");
generateButton.setEnabled(true);
- generateLabel.setText("Data generation failed");
+ updateCounts();
}
- public void onSuccess(Integer result) {
- generateLabel.setText("" + result + " Expense Reports");
+ public void onSuccess(Void result) {
+ statusLabel.setText("Data generation succeeded");
generateButton.setEnabled(true);
+ updateCounts();
}
});
}
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/server/DataGenerationServiceImpl.java
Wed May 12 10:44:13 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/server/DataGenerationServiceImpl.java
Wed May 12 11:38:12 2010
@@ -15,6 +15,7 @@
*/
package com.google.gwt.sample.expenses.gwt.server;
+import com.google.apphosting.api.DeadlineExceededException;
import com.google.gwt.sample.expenses.gwt.client.DataGenerationService;
import com.google.gwt.sample.expenses.server.domain.Employee;
import com.google.gwt.sample.expenses.server.domain.Expense;
@@ -38,10 +39,6 @@
public class DataGenerationServiceImpl extends RemoteServiceServlet
implements
DataGenerationService {
- private static final double AIRFARE = 600;
-
- private static final double BREAKFAST = 15;
-
// Must be in sync with DESCRIPTIONS
private static String[] CATEGORIES = {
"Local Transportation", "Local Transportation", "Local
Transportation",
@@ -116,6 +113,18 @@
"Rochester, New York", "Winston-Salem, North Carolina",
"Durham, North Carolina", "Reno, Nevada", "Laredo, Texas"};
+ private static final double COST_AIRFARE = 600;
+
+ private static final double COST_BREAKFAST = 15;
+
+ private static final double COST_DINNER = 60;
+
+ private static final double COST_HOTEL = 300;
+
+ private static final double COST_LUNCH = 25;
+
+ private static final double COST_SUNDRY = 100;
+
private static final String[] DEPARTMENTS = {
"Operations", "Engineering", "Finance", "Marketing", "Sales"};
@@ -149,8 +158,6 @@
"Outreach", "Training", "Self", "Co-Workers", "Customers", "Hotel",
"Motel ", "Holiday Inn", "Private Apartment", "Corporate Apartment"};
- private static final double DINNER = 60;
-
// 11% of females hyphenate their last names
private static final double FEMALE_HYPHENATE = 0.11;
@@ -158,8 +165,6 @@
private static List<String> femaleNames = new ArrayList<String>();
- private static final double HOTEL = 300;
-
private static final DataGenerationServiceImpl instance = new
DataGenerationServiceImpl();
private static List<Double> lastNameFreqs = new ArrayList<Double>();
@@ -168,8 +173,6 @@
private static final Logger log =
Logger.getLogger(DataGenerationServiceImpl.class.getName());
- private static final double LUNCH = 25;
-
// 2% of males hyphenate their last names
private static final double MALE_HYPHENATE = 0.02;
@@ -1391,58 +1394,55 @@
"Lost, customer meeting", "Customer meeting, sales opportunity",
"Sales opportunity, emergency", "Emergency, backup", "Backup,
research"};
- private static final double SUNDRY = 100;
-
public static DataGenerationServiceImpl getInstance() {
return instance;
}
private long endTime;
-
- // List<Object> toPersist = new ArrayList<Object>();
-
+
private Random rand = new Random();
public void delete() {
- for (Employee e : Employee.findAllEmployees()) {
- e.remove();
- }
- for (Report r : Report.findAllReports()) {
- r.remove();
- }
- for (Expense e : Expense.findAllExpenses()) {
- e.remove();
+ try {
+ log.info("Expenses before: " + Expense.countExpenses());
+ List<Expense> expenses = Expense.findAllExpenses();
+ log.info("ids from " + expenses.get(0).getId() + " to " +
+ expenses.get(expenses.size() - 1).getId());
+ for (Expense e : expenses) {
+ log.info("Deleting expense " + e.getId());
+ e.remove();
+ }
+ for (Report r : Report.findAllReports()) {
+ log.info("Deleting report " + r.getId());
+ r.remove();
+ }
+ for (Employee e : Employee.findAllEmployees()) {
+ log.info("Deleting employee " + e.getId());
+ e.remove();
+ }
+ } catch (DeadlineExceededException e) {
+ log.info("Expenses after: " + Expense.countExpenses());
+ return;
}
}
- public int generate(int millis) {
+ public void generate(int millis) {
long startTime = System.currentTimeMillis();
endTime = startTime + millis;
-// log.info("In generate(" + millis + ") at " + startTime + " (left = "
+ (endTime - startTime) + ")");
int startEmployees = (int) Employee.countEmployees();
int startReports = (int) Report.countReports();
int numEmployees;
synchronized (DataGenerationServiceImpl.class) {
-// long start, end;
try {
if (lastNames.size() == 0) {
-// start = System.currentTimeMillis();
readFile("dist.all.last.txt", lastNames, lastNameFreqs);
-// end = System.currentTimeMillis();
-// log.info("Read dist.all.last.txt in " + (end - start) + "
milliseconds");
}
if (femaleNames.size() == 0) {
-// start = System.currentTimeMillis();
readFile("dist.female.first.txt", femaleNames, femaleNameFreqs);
-// end = System.currentTimeMillis();
-// log.info("Read dist.female.first.txt in " + (end - start) + "
milliseconds");
}
if (maleNames.size() == 0) {
-// start = System.currentTimeMillis();
readFile("dist.male.first.txt", maleNames, maleNameFreqs);
-// end = System.currentTimeMillis();
-// log.info("Read dist.male.first.txt in " + (end - start) + "
milliseconds");
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
@@ -1451,15 +1451,9 @@
// Choose department and make a manager
int department = rand.nextInt(DEPARTMENTS.length);
-// long supervisorId = makeEmployee(department, 0, false);
-// if (supervisorId == -1) {
-// return startReports;
-// }
long supervisorId = 1;
- long time;
- while ((time = System.currentTimeMillis()) < endTime) {
-// log.info("Calling makeEmployee from generate at " + time + " (left
= " + (endTime - time) + ")");
+ while (System.currentTimeMillis() < endTime) {
makeEmployee(department, supervisorId, true);
}
@@ -1470,13 +1464,15 @@
log.info("Generated " + employeesCreated + " employees and " +
reportsCreated + " reports in " +
(System.currentTimeMillis() - startTime) + " milliseconds");
-
- return numReports;
}
- public int getNumReports() {
+ public List<Integer> getCounts() {
synchronized (DataGenerationServiceImpl.class) {
- return (int) Report.countReports();
+ List<Integer> counts = new ArrayList<Integer>(3);
+ counts.add((int) Employee.countEmployees());
+ counts.add((int) Report.countReports());
+ counts.add((int) Expense.countExpenses());
+ return counts;
}
}
@@ -1503,7 +1499,6 @@
private long makeEmployee(int department, long supervisorId, boolean
makeExpenses) {
long time = System.currentTimeMillis();
if (time >= endTime) {
-// log.info("Returning from makeEmployee at " + time + " (left = " +
(endTime - time) + ")");
return -1;
}
@@ -1528,17 +1523,14 @@
employee.setDepartment(DEPARTMENTS[department]);
employee.setPassword("");
-// long start = System.currentTimeMillis();
employee.persist();
-// log.info("Persisted employee in " + (System.currentTimeMillis() -
start) + " millis");
long id = employee.getId();
- String dept = employee.getDepartment();
if (makeExpenses) {
int numExpenseReports = rand.nextInt(96) + 5;
for (int i = 0; i < numExpenseReports; i++) {
- if (!makeExpenseReport(id, supervisorId, dept)) {
+ if (!makeExpenseReport(id, department, supervisorId)) {
return id;
}
}
@@ -1558,16 +1550,12 @@
expense.setApproval("");
expense.setReasonDenied("");
-// long start = System.currentTimeMillis();
expense.persist();
-// log.info("Persisted expense in " + (System.currentTimeMillis() -
start) + " millis");
}
- private boolean makeExpenseReport(long employeeId, long supervisorId,
- String department) {
+ private boolean makeExpenseReport(long employeeId, int department, long
supervisorId) {
long time = System.currentTimeMillis();
if (time >= endTime) {
-// log.info("Returning from makeExpenseReport at " + time + " (left
= " + (endTime - time) + ")");
return false;
}
@@ -1578,7 +1566,7 @@
Report report = new Report();
report.setReporterKey(employeeId);
- report.setDepartment(department);
+ report.setDepartment(DEPARTMENTS[department]);
report.setApprovedSupervisorKey(supervisorId);
report.setCreated(createdDate);
boolean travel = rand.nextInt(4) == 0;
@@ -1600,10 +1588,7 @@
report.setNotes(NOTES[rand.nextInt(NOTES.length)]);
}
-// long start = System.currentTimeMillis();
- report.persist();
-// log.info("Persisted report in " + (System.currentTimeMillis() -
start) + " millis");
-
+ report.persist();
long id = report.getId();
if (travel) {
@@ -1615,18 +1600,18 @@
}
makeExpenseDetail(id, new Date(millis - days * MILLIS_PER_DAY),
- "Air Travel", "Outbound flight", amount(AIRFARE));
+ "Air Travel", "Outbound flight", amount(COST_AIRFARE));
makeExpenseDetail(id, new Date(millis - MILLIS_PER_DAY / 2),
- "Air Travel", "Return flight", amount(AIRFARE));
+ "Air Travel", "Return flight", amount(COST_AIRFARE));
for (int i = 0; i < days; i++) {
makeExpenseDetail(id, new Date(millis - (days - i) * MILLIS_PER_DAY
- - 10 * MILLIS_PER_HOUR), "Dining", "Breakfast",
amount(BREAKFAST));
+ - 10 * MILLIS_PER_HOUR), "Dining", "Breakfast",
amount(COST_BREAKFAST));
makeExpenseDetail(id, new Date(millis - (days - i) *
MILLIS_PER_DAY - 6
- * MILLIS_PER_HOUR), "Dining", "Lunch", amount(LUNCH));
+ * MILLIS_PER_HOUR), "Dining", "Lunch", amount(COST_LUNCH));
makeExpenseDetail(id, new Date(millis - (days - i) *
MILLIS_PER_DAY - 2
- * MILLIS_PER_HOUR), "Dining", "Dinner", amount(DINNER));
+ * MILLIS_PER_HOUR), "Dining", "Dinner", amount(COST_DINNER));
makeExpenseDetail(id, new Date(millis - (days - i) *
MILLIS_PER_DAY),
- "Lodging", "Hotel", amount(HOTEL));
+ "Lodging", "Hotel", amount(COST_HOTEL));
}
} else {
int numExpenses = rand.nextInt(5) + 1;
@@ -1635,11 +1620,10 @@
long detailOffset = rand.nextInt(60 * 60 * 24 * days) * 1000L;
Date date = new Date(createdDate.getTime() - detailOffset);
makeExpenseDetail(id, date, CATEGORIES[index], DESCRIPTIONS[index],
- amount(SUNDRY));
+ amount(COST_SUNDRY));
}
}
-// log.info("Made report in " + (System.currentTimeMillis() - time) + "
millis");
return true;
}
=======================================
--- /branches/2.1/bikeshed/war/WEB-INF/web.xml Wed May 12 08:28:52 2010
+++ /branches/2.1/bikeshed/war/WEB-INF/web.xml Wed May 12 11:38:12 2010
@@ -88,6 +88,25 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
+
+ <!-- Enable remote API on Java (for datastore bulkloader). You also need
to add appengine-tools.jar to war/WEB-INF/lib -->
+ <servlet>
+ <servlet-name>remoteapi</servlet-name>
+
<servlet-class>com.google.apphosting.utils.remoteapi.RemoteApiServlet</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>remoteapi</servlet-name>
+ <url-pattern>/remote_api</url-pattern>
+ </servlet-mapping>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>remoteapi</web-resource-name>
+ <url-pattern>/remote_api</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>admin</role-name>
+ </auth-constraint>
+ </security-constraint>
<!-- Enable remote API on Java (for datastore bulkloader). -->
<!-- You also need to add appengine-tools-api.jar to war/WEB-INF/lib -->
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors