Revision: 8526
Author: rj...@google.com
Date: Thu Aug 12 08:15:08 2010
Log: Extends DynaTableRF with a client call to Person#persist.

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

Review by: robertvaw...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=8526

Modified:
/trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/CalendarProvider.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/DynaTableRf.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/DynaTableWidget.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/SchoolCalendarWidget.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java /trunk/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java /trunk/user/src/com/google/gwt/requestfactory/server/RequestFactoryServlet.java
 /trunk/user/src/com/google/gwt/valuestore/shared/SyncResult.java

=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml Thu Jul 29 06:36:34 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml Thu Aug 12 08:15:08 2010
@@ -18,6 +18,18 @@

   <inherits name='com.google.gwt.user.User' />
   <inherits name='com.google.gwt.requestfactory.RequestFactory' />
+
+  <inherits name='com.google.gwt.logging.Logging'/>
+  <set-property name="gwt.logging.enabled" value="TRUE"/>
+  <set-property name="gwt.logging.logLevel" value="INFO"/>
+  <set-property name="gwt.logging.consoleHandler" value="ENABLED" />
+ <set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
+  <set-property name="gwt.logging.firebugHandler" value="ENABLED" />
+  <set-property name="gwt.logging.hasWidgetsHandler" value="DISABLED" />
+  <set-property name="gwt.logging.popupHandler" value="DISABLED" />
+  <set-property name="gwt.logging.systemHandler" value="ENABLED" />
+  <set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED" />
+
<entry-point class='com.google.gwt.sample.dynatablerf.client.DynaTableRf' />

<set-configuration-property name="CssResource.obfuscationPrefix" value="empty" />
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/CalendarProvider.java Mon Aug 2 18:09:28 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/CalendarProvider.java Thu Aug 12 08:15:08 2010
@@ -18,6 +18,7 @@
 import com.google.gwt.event.shared.HandlerManager;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.RequestObject;
 import com.google.gwt.sample.dynatablerf.client.events.DataAvailableEvent;
 import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory;
 import com.google.gwt.sample.dynatablerf.shared.PersonProxy;
@@ -25,12 +26,15 @@

 import java.util.List;
 import java.util.Set;
+import java.util.logging.Logger;

 /**
* A data provider that bridges the provides row level updates from the data
  * available through a <@link SchoolCalendarService>.
  */
 public class CalendarProvider {
+ private static final Logger log = Logger.getLogger(CalendarProvider.class.getName());
+
   private final HandlerManager eventBus = new HandlerManager(this);

   private int lastMaxRows = -1;
@@ -69,12 +73,52 @@
             lastMaxRows = maxRows;
             lastPeople = response;
             pushResults(startRow, response);
-          }
+
+            if (response.size() > 0) {
+              demoPersist(response.get(0));
+            }
+          }
+
         });
   }
+
+  private void demoPersist(PersonProxy someone) {
+    /*
+     * Create a request to call someone's persist method.
+     */
+ RequestObject<Void> request = requests.personRequest().persist(someone);
+
+    someone = request.edit(someone);
+    someone.setName("Ray Ryan");
+    someone.setDescription("Was here");
+
+    request.fire(new Receiver<Void>() {
+ public void onSuccess(Void isNull, /* syncResults going away very soon */
+      Set<SyncResult> syncResults) {
+        /*
+         * A PersonProxyChanged should have fired. By M4, subtypes like
+ * PersonProxyChanged should go away and be replaced by a more general
+         * ProxyUpdateEvent
+         */
+        log.info("The persist call worked, did you see an update event?");
+      }
+
+      /*
+       * Coming soon
+       *
+ * void onViolation(Set<ConstraintViolation> violations); void onError(
+       * ... tbd ... );
+       *
+       * But likely this will come first, not sure who is dealing with
+       * serializing ConstraintViolation. Sorry.
+       *
+       * void onViolation(Set<SyncResult> syncResults) { ... }
+       */
+
+    });
+  }

   private void pushResults(int startRow, List<PersonProxy> people) {
-    // TODO(rjrjr) RequestFactory should probably provide this event.
     eventBus.fireEvent(new DataAvailableEvent(startRow, people));
   }
 }
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/DynaTableRf.java Mon Aug 2 18:09:28 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/DynaTableRf.java Thu Aug 12 08:15:08 2010
@@ -48,7 +48,7 @@

     CalendarProvider provider = new CalendarProvider(requests);

-    calendar = new SchoolCalendarWidget(provider, 15);
+ calendar = new SchoolCalendarWidget(new DynaTableWidget(eventBus, provider, 15));
     filter = new DayFilterWidget(eventBus);

     RootLayoutPanel.get().add(
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/DynaTableWidget.java Mon Aug 2 18:09:28 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/DynaTableWidget.java Thu Aug 12 08:15:08 2010
@@ -18,10 +18,12 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.shared.HandlerManager;
 import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.sample.dynatablerf.client.events.NavigationEvent;
 import com.google.gwt.sample.dynatablerf.client.events.DataAvailableEvent;
+import com.google.gwt.sample.dynatablerf.client.events.NavigationEvent;
 import com.google.gwt.sample.dynatablerf.shared.PersonProxy;
+import com.google.gwt.sample.dynatablerf.shared.PersonProxyChanged;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.uibinder.client.UiHandler;
@@ -34,13 +36,13 @@
 import com.google.gwt.user.client.ui.Widget;

 import java.util.List;
+import java.util.logging.Logger;

 /**
* A composite Widget that implements the main interface for the dynamic table,
  * including the data table, status indicators, and paging buttons.
  */
 public class DynaTableWidget extends Composite {
-
   interface Binder extends UiBinder<Widget, DynaTableWidget> {
   }

@@ -69,6 +71,8 @@
       body.setHTML(html);
     }
   }
+
+ private static final Logger log = Logger.getLogger(DynaTableWidget.class.getName());

   // TODO: Re-add error handling
   @SuppressWarnings("unused")
@@ -95,11 +99,30 @@

   private HandlerRegistration rowDataRegistration;

-  public DynaTableWidget(CalendarProvider provider, int rowCount) {
+ public DynaTableWidget(HandlerManager eventBus, CalendarProvider provider,
+      int rowCount) {
     this.provider = provider;
     Binder binder = GWT.create(Binder.class);
     initWidget(binder.createAndBindUi(this));
     initTable(rowCount);
+
+    eventBus.addHandler(PersonProxyChanged.TYPE,
+        new PersonProxyChanged.Handler() {
+          public void onPersonChanged(PersonProxyChanged event) {
+            /*
+ * At the moment this proxy includes all the new property values, + * but that's an accident. Only its id property should be populated.
+             *
+ * The correct thing to do, and soon the only thing that will work, + * is to fire an appropriate request to pick up the new values. No, + * I'm not happy about the extra round trip. Still thinking about
+             * that.
+             */
+            log.info("Look who changed, time to repaint some things: "
+                + event.getRecord());
+          }
+        });
+
   }

   public void clearStatusText() {
@@ -114,6 +137,25 @@
     navbar.gotoNext.setEnabled(false);

     setStatusText("Please wait...");
+
+    /*
+ * TODO the cell widgets reverse this relationship, to stay async friendly.
+     *
+ * This widget would implement HasRows, and would not know directly about + * its data provider. Instead, the provider would know about the widget via
+     * something like
+     *
+     * dynaTableWidget.addRangeChangeHandler(calendarProvider)
+     *
+     * and on response would call
+     *
+     * dynaTableWidget.setRowValues( ... ) directly
+     *
+ * ListViewAdapter (soon to be renamed something like DataProvider) exists
+     * to make this convenient when dealing with lists, and to allow one
+     * provider to serve multiple HasData clients
+     * (AbstractListViewAdapter#addView(HasData<T>))
+     */
     provider.updateRowData(startRow, grid.getRowCount() - 1);
   }

@@ -167,6 +209,7 @@
     int srcRowIndex = 0;
     int srcRowCount = people.size();
     int destRowIndex = 1; // skip navbar row
+
     for (; srcRowIndex < srcRowCount; ++srcRowIndex, ++destRowIndex) {
       PersonProxy p = people.get(srcRowIndex);
       grid.setText(destRowIndex, 0, p.getName());
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/SchoolCalendarWidget.java Mon Aug 2 18:09:28 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/SchoolCalendarWidget.java Thu Aug 12 08:15:08 2010
@@ -31,8 +31,8 @@

   private ScheduledCommand pendingRefresh;

-  public SchoolCalendarWidget(CalendarProvider provider, int visibleRows) {
-    dynaTable = new DynaTableWidget(provider, visibleRows);
+  public SchoolCalendarWidget(DynaTableWidget dynaTable) {
+    this.dynaTable = dynaTable;
     initWidget(dynaTable);
   }

=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java Mon Aug 2 10:03:54 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/domain/Person.java Thu Aug 12 08:15:08 2010
@@ -15,30 +15,46 @@
  */
 package com.google.gwt.sample.dynatablerf.domain;

+import com.google.gwt.sample.dynatablerf.server.SchoolCalendarService;
+
 /**
  * Hold relevant data for Person.
  */
 public abstract class Person {
-  private static Long serial = 1L;
+  /**
+ * The {...@link RequestFactory} requires a static finder method for each proxied type.
+   * Soon it should allow you to customize how instances are found.
+   */
+  public static Person findPerson(Long id) {
+    return SchoolCalendarService.findPerson(id);
+  }

   private String description = "DESC";

   private String name;
-
-  private final Long id;
+
+  private Long id;
+
+  private Integer version = 0;

   public Person() {
-    id = serial++;
   }

   public String getDescription() {
     return description;
   }
-
+
+  /**
+ * The {...@link RequestFactory} requires a Long id property for each proxied type.
+   * <p>
+   * The requirement for some kind of id object with proper hash / equals
+ * semantics is not going away, but it should become possible to use types
+   * other than Long, and properties other than "id".
+   */
   public Long getId() {
     return id;
   }
-
+
   public String getName() {
     return name;
   }
@@ -49,15 +65,42 @@

   public abstract String getSchedule(boolean[] daysFilter);

+  /**
+ * The {...@link RequestFactory} requires an Integer version property for each proxied + * type, but makes no good use of it. This requirement will be removed soon.
+   */
   public Integer getVersion() {
-    return 1;
+    return version;
+  }
+
+  /**
+ * When this was written the {...@link RequestFactory} required a persist method per type. + * That requirement should be relaxed very soon (and may well have been already
+   * if we forget to update this comment).
+   */
+  public void persist() {
+    SchoolCalendarService.persist(this);
   }

   public void setDescription(String description) {
     this.description = description;
   }
+
+  public void setId(Long id) {
+    this.id = id;
+  }

   public void setName(String name) {
     this.name = name;
   }
-}
+
+  public void setVersion(Integer version) {
+    this.version = version;
+  }
+
+  @Override
+  public String toString() {
+    return "Person [description=" + description + ", id=" + id + ", name="
+        + name + ", version=" + version + "]";
+  }
+}
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java Fri Jul 23 15:42:40 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/server/SchoolCalendarService.java Thu Aug 12 08:15:08 2010
@@ -24,13 +24,16 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;

 /**
  * The server side service class.
  */
 public class SchoolCalendarService {
+  private static Long serial = 0L;

   private static final String[] FIRST_NAMES = new String[] {
       "Inman", "Sally", "Omar", "Teddy", "Jimmy", "Cathy", "Barney", "Fred",
@@ -55,7 +58,7 @@

   private static final int STUDENTS_PER_PROF = 5;

-  private static final List<Person> people = new ArrayList<Person>();
+ private static final Map<Long, Person> people = new LinkedHashMap<Long, Person>();

   private static final Random rnd = new Random(3);

@@ -74,16 +77,28 @@
       return Collections.emptyList();
     }

-    return people.subList(startIndex, end);
+    return new ArrayList<Person>(people.values()).subList(startIndex, end);
   }

   private static void generateRandomPeople() {
     if (people.isEmpty())
       for (int i = 0; i < MAX_PEOPLE; ++i) {
         Person person = generateRandomPerson();
-        people.add(person);
+        persist(person);
       }
   }
+
+  public static Person findPerson(Long id) {
+    return people.get(id);
+  }
+
+  public static void persist(Person person) {
+    if (person.getId() == null) {
+      person.setId(++serial);
+    }
+    person.setVersion(person.getVersion() + 1);
+    people.put(person.getId(), person);
+  }

   private static Person generateRandomPerson() {
     // 1 out of every so many people is a prof.
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java Fri Jul 23 15:42:40 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/DynaTableRequestFactory.java Thu Aug 12 08:15:08 2010
@@ -15,9 +15,12 @@
  */
 package com.google.gwt.sample.dynatablerf.shared;

+import com.google.gwt.requestfactory.shared.Instance;
 import com.google.gwt.requestfactory.shared.RecordListRequest;
 import com.google.gwt.requestfactory.shared.RequestFactory;
+import com.google.gwt.requestfactory.shared.RequestObject;
 import com.google.gwt.requestfactory.shared.Service;
+import com.google.gwt.sample.dynatablerf.domain.Person;
 import com.google.gwt.sample.dynatablerf.server.SchoolCalendarService;

 /**
@@ -26,13 +29,25 @@
  */
 public interface DynaTableRequestFactory extends RequestFactory {

+  /**
+   * Source of request objects for the Person class.
+   */
+  @Service(Person.class)
+  interface PersonRequest {
+    @Instance
+    RequestObject<Void> persist(PersonProxy person);
+  }
+
   /**
    * Source of request objects for the SchoolCalendarService.
    */
   @Service(SchoolCalendarService.class)
   interface SchoolCalendarRequest {
+    // TODO(amitmanjhi, cromwellian) RequestObject<List<PersonProxy>>
     RecordListRequest<PersonProxy> getPeople(int startIndex, int maxCount);
   }
-
+
+  PersonRequest personRequest();
+
   SchoolCalendarRequest schoolCalendarRequest();
 }
=======================================
--- /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java Thu Jul 29 12:54:53 2010 +++ /trunk/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java Thu Aug 12 08:15:08 2010
@@ -33,9 +33,13 @@
Property<String> description = new Property<String>("description", "Description", String.class); Property<String> schedule = new Property<String>("schedule", "Schedule", String.class);

-  String getSchedule();
-
   String getDescription();

   String getName();
-}
+
+  String getSchedule();
+
+  void setDescription(String description);
+
+  void setName(String name);
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java Thu Aug 5 15:15:34 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java Thu Aug 12 08:15:08 2010
@@ -52,6 +52,9 @@
  * An implementation of RequestProcessor for JSON encoded payloads.
  */
 public class JsonRequestProcessor implements RequestProcessor<String> {
+
+ private static final Logger log = Logger.getLogger(JsonRequestProcessor.class.getName());
+
   // TODO should we consume String, InputStream, or JSONObject?
   /**
    * A class representing the pair of a domain entity and its corresponding
@@ -71,7 +74,7 @@

   public static Set<String> initBlackList() {
     Set<String> blackList = new HashSet<String>();
-    for (String str : new String[]{"password"}) {
+    for (String str : new String[] {"password"}) {
       blackList.add(str);
     }
     return Collections.unmodifiableSet(blackList);
@@ -158,8 +161,7 @@
         int ordinal = Integer.parseInt(parameterValue);
         Method valuesMethod = parameterType.getDeclaredMethod("values",
             new Class[0]);
-        Logger.getLogger(this.getClass().getName()).severe(
-            "Type is " + parameterType + " valuesMethod " + valuesMethod);
+ log.severe("Type is " + parameterType + " valuesMethod " + valuesMethod);

         if (valuesMethod != null) {
           valuesMethod.setAccessible(true);
@@ -612,7 +614,9 @@
           recordObject.get("id"), propertiesInRecord.get("id"));

       // persist
-      Set<ConstraintViolation<Object>> violations = null;
+
+      Set<ConstraintViolation<Object>> violations = Collections.emptySet();
+
       if (writeOperation == WriteOperation.DELETE) {
         entity.getMethod("remove").invoke(entityInstance);
       } else {
@@ -635,10 +639,24 @@
         }

         // validations check..
- ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
-        Validator validator = validatorFactory.getValidator();
-
-        violations = validator.validate(entityInstance);
+        Validator validator = null;
+        try {
+ ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
+          validator = validatorFactory.getValidator();
+        } catch (Exception e) {
+          /*
+ * This is JBoss's clumsy way of telling us that the system has not
+           * been configured.
+           */
+          log.info(String.format(
+ "Ingnoring exception caught initializing bean validation framework. " + + "It is probably unconfigured or misconfigured. [%s] %s ",
+              e.getClass().getName(), e.getLocalizedMessage()));
+        }
+
+        if (validator != null) {
+          violations = validator.validate(entityInstance);
+        }
         if (violations.isEmpty()) {
           entity.getMethod("persist").invoke(entityInstance);
         }
@@ -648,6 +666,8 @@
       return getReturnRecord(writeOperation, entityInstance, recordObject,
           violations);
     } catch (Exception ex) {
+      log.severe(String.format("Caught exception [%s] %s",
+          ex.getClass().getName(), ex.getLocalizedMessage()));
       return getReturnRecordForException(writeOperation, recordObject, ex);
     }
   }
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/server/RequestFactoryServlet.java Thu Aug 5 15:15:34 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/server/RequestFactoryServlet.java Thu Aug 12 08:15:08 2010
@@ -58,7 +58,6 @@
   private static final String JSON_CHARSET = "UTF-8";
   private static final String JSON_CONTENT_TYPE = "application/json";

-  @SuppressWarnings("unchecked")
   @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
       throws IOException, ServletException {
=======================================
--- /trunk/user/src/com/google/gwt/valuestore/shared/SyncResult.java Thu Aug 5 10:04:19 2010 +++ /trunk/user/src/com/google/gwt/valuestore/shared/SyncResult.java Thu Aug 12 08:15:08 2010
@@ -29,6 +29,7 @@
   // TODO: move violations out of the SyncResult...
   boolean hasViolations();

+  // TODO: futureId isn't working out so well, leaving soon
   Long getFutureId();

   Record getRecord();

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to