Posts tagged ‘Google App Engine 1.3.1’

Query Objects not just Strings

Haha, I just thought how weird that title would look to anyone who isn’t a programmer (why would you want to ask sting something).

Stupid jokes aside, I thought it would be important to write down how to query Objects, like dates or people in Google App Engine. The concept is very simple, though you may have to put in a little extra thought. For example, lets query a date. We want to design a calendar that will store events for different days, and we want these events to have specific times (that should be obvious). How do we search for these when we need to?

Say we’re searching for all events on March 22nd. This will include my “Wake up” alert at 6:30 am as well as my “Appointment with Mr. Money” from 10:00 am to 2:00 pm. In any query language you’ll have to say, “Hey, db, I want everything between 12:00 am and 11:59:59 on March 22nd.” To do this in Google App Engine you’ll do the following, (you’ll also do similar things with other Objects). Note, you may want to read my post on Google App Engine Datastore to get some of the basics.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//...
//open your persistence manager
PersistenceManager pm = PMF.get().getPersistenceManager()
//create a new Query
Query eventQuery = pm.newQuery(Event.class);
//set the filter for the Query. Notice that there is a range the date must fall in, this may or may not be necessary on other Objects.
eventQuery.setFilter("startDate <= startDateParam && startDate <= endDateParam");
//declare the parameters of the Query
eventQuery.declareParameters("java.util.Date startDateParam, java.util.Date endDateParam"); //notice the full address of the Date class
//set any ordering you want
eventQuery.setOrdering("startDate");
//execute the query
List<Event> events = (List<Event>) eventQuery.execute(startDate, endDate);
//...

You’ll notice that I used java.util.Date even though a great majority of the methods in this class are deprecated. The reason why is because of a bug I came across (I feel okay calling it a bug since other people have had problems with it and since when I changed the class name it made no difference but when I changed my GregorianCalendars to Dates it worked fine.) Maybe they will fix it and you won’t have the same problem.

Post Ratings: (No Ratings Yet)

Don’t forget your static files

Before you deploy your app in Google App Engine, you must configure your app to include static files. Important files—like your css files! So, if you want to have your application look the same in testing and in deployment, then follow these steps.

Open appengine-web.xml
The first thing you’ll need to do is fine the appengine-web.xml file located in [your program folder] > war > WEB-INF. It should look something like this (in Source view):

1
2
3
4
5
6
7
8
9
10
11
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
     <application>application</application>
     <version>1</version>
 
     <!-- Configure java.util.logging -->
     <system-properties>
          <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
     </system-properties>
     <ssl-enabled>true</ssl-enabled>
     <sessions-enabled>true</sessions-enabled>
</appengine-web-app>

Once it’s open, you’ll need to insert a static-files tag into the file (it doesn’t matter where, but I usually put it after the version attribute). Between the open and close static-files tags put the include tag with apath attribute. It should look like this:

5
6
7
8
9
10
<static-files>
      <include path="/favicon.ico" />
      <include path="/css/screen.css" />
      <include path="/img/*.png" />
      <include path="/js/*" />
</static-files>

As you can see, you can use the * wildcard so in order to save a lot of potential typing.

All together it should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
     <application>prs-app</application>
     <version>1</version>
     <static-files>
	<include path="/favicon.ico" />
  	<include path="/css/screen.css" />
  	<include path="/img/*.png" />
  	<include path="/js/*" />
     </static-files>
 
     <!-- Configure java.util.logging -->
     <system-properties>
         <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
     </system-properties>
     <ssl-enabled>true</ssl-enabled>
     <sessions-enabled>true</sessions-enabled>
</appengine-web-app>
Post Ratings: (No Ratings Yet)

Co-custody + Google Datastore = Big No No

I learned something today while I was debugging some code: It turns out that a child class can only belong to one parent class in the datastore. If you attempt to use a child class in two different places, it may seem to work at first, but then you’ll get an excetpion and error message like this:
java.lang.ClassCastException: oid is not instanceof javax.jdo.identity.ObjectIdentity ...
It was strange, one minute this code was working fine, after I worked on some other code I went back and it stopped working. Here is what I was trying to do:

I’m working on a project that will track real estate listings (Listing) and clients (Person). Each of those Objects need an Address, so I thought I’d just use the same bean like I would in with a relational database table. Turns out, however, you can’t do that in Google’s Datastore.

To quote Max Ross of Google, “Due to the nature of primary keys in the app engine datastore, a [sub]class can only have a single owner. We detect other flavors of this scenario when the entity meta-data is loaded but not this particular variant” (1). Max did say later in the post that he would look into how they could repair that, but I don’t really know if that’s going to happen any time soon.

In order to not have this bug, I’ll have to use two different Addresses for those beans now. Sigh.

Post Ratings: (No Ratings Yet)

View Datastore Data

Want to view what information is stored in your datastore in Google App Engine? Go to http://localhost:8888/_ah/admin (or http://localhost:8080/_ah/admin if you are using that port).

Here is what you’ll see:
Datastore View

Post Ratings: (No Ratings Yet)

FrontController, ApplicationController, and Interactor

I mentioned in the post: Google App Store Datastore that I make data persistent by making requests to a FrontController which forwards the request to an ApplicationController which calls the needed class which implements Interactor. This is important for several reasons: (1) It is more secure, there is only one servlet to access my server. (2) Because we can call any class using an ApplicationController and an Interactor.

The following is the code for each of these classes:
FrontController

@SuppressWarnings("serial")
public class FrontController extends HttpServlet {
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		ApplicationController ac = new ApplicationController(req, resp); //calls ApplicationController
	}
 
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		this.doGet(req, resp); //doing this will allow you to call the same method
                                                   //whether a developer uses GET or POST
	}
}

ApplicationController

public class ApplicationController {
	HashMap controls = new HashMap();
 
	private void putControl() { //Key is what the application will call, Class is the program to return
		controls.put("addfood", AddFood.class);//do this with all the classes you may need to call
	}
 
	public ApplicationController(HttpServletRequest request, HttpServletResponse response) {
		putControl();
		String action = request.getParameter("a").toLowerCase();//in the url string, ?a=addfood&amp;...
 
		Class aClass = controls.get(action);
 
		try {
			if (aClass != null) {
				Interactor anInteractor = (Interactor) aClass.newInstance();
				anInteractor.invoke(request, response);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Interactor

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public interface Interactor {
	void invoke(HttpServletRequest request, HttpServletResponse response);
}

Note: Classes that implement the Interactor must implement the invoke method. Method signature looks like public class AddFood implements Interactor

Post Ratings: (No Ratings Yet)