Monday, November 10, 2014

Google App Engine Pitfalls 2.0

Logging - add this:

 private static final Logger log = Logger.getLogger(GreetingServiceImpl.class.getName());  



...and this...for some reason...

 log.setLevel(Level.INFO);  



...and of course.

 log.info("The query returned " + pq.countEntities() + " entries.");  

Google App Engine and Datastore Pitfalls

Working with Google App Engine and hit some interesting "learning opportunities":

 private void persistData(String[] input, User currentUser) {  
   String weeklystatusName = "weeklystatuslist";  
   Key statusKey = KeyFactory.createKey("WeeklyStatus", weeklystatusName);  
   Date date = new Date();  
   Entity status = new Entity("Status", statusKey);  
   status.setProperty("userid", currentUser.getNickname());  
   status.setProperty("date", date);  
   status.setProperty("name", input[0]);  
   status.setProperty("date_begin", input[1]);  
   status.setProperty("date_end", input[2]);  
   status.setProperty("client_name", input[3]);  
   status.setProperty("accomplishments", input[4]);  
   status.setProperty("risks", input[5]);  
   status.setProperty("next_week", input[6]);  
   status.setProperty("hours", input[7]);  
   status.setProperty("pto", input[8]);  
   status.setProperty("distribution", input[9]);  
   status.setProperty("submitted", input[10]);  
   DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();  
   datastore.put(status);  
 }  


Running a query on the datastore didn't return anything though I could see my data while browsing.  And...the query didn't work in GQL either.  Finally I discovered that what I thought were Strings saved to the datastore were actually User objects.  Datastore doesn't care what you pass to it...it'll save that object.  But just because it looks like a string doesn't mean it is.

One getNickname() later...query worked.  Added a sort...

select * from Status where userid='user1' order by date desc

Query broke.  Gah.  No wait...it says I need to add an index.  Added that to WEB-INF and redeployed.

 <?xml version="1.0" encoding="utf-8"?>  
 <datastore-indexes autoGenerate="true">  
      <datastore-index kind="Status" ancestor="false" source="manual">  
           <property name="userid" direction="asc"/>  
           <property name="date" direction="desc"/>  
      </datastore-index>  
 </datastore-indexes>  

Still failed.  Eventually I realized that "kind" has to be the name of my table.  (My table was called "Status" not "Statuses".)  It sort of makes sense but not really, since you might expect an index could be applied to multiple tables or at least that I'd get an error message if I tried to create an index that wasn't connected to an existing table-space.

Datastore seems to be designed as Fisher-Price My First Database in some ways but then it uses unusual standards (by Oracle/DB2/mySQL standards) and doesn't provide detailed documentation.  Still though, very cool once you get used to it.