Stony ground on the Google App Engine, Shopper app #8

Hello :)

A couple of days ago, I tried to deploy the GAE webapplication to the google appspot.
What hat happened? Well… Nothing :D While the webservice-applciation works fine on my local machine nothing seemed to run on the
GAE appspot. Hmm not so cool :P Trying to find the error, and fix it costed me a lot of time. So this short posting
is again about the Google app engine and the problems i had.
First of all the Entity datamodel of the shopper application was quite sloppy and i reworked it. I dropped the Group entity, and istead of it
I added a simple String field to the Member entity called “groupname” this makes it esier on the datastore to retrieve the members of a group.
There are some changes here and there on the datamodel but they aren’t very big.

Querying the Datastore

Say you have a one-to-Many relationship of 2 of your entities in the datastore. I tried to fetch the data of the “mapper” entity and thought the
child entity would be fetched automatically. This was “somehow” the case because in my code there were parts where i “touched” the Getter-Methods for the
child entities. Once you call these methods the entities are going to be retrieved from the datastore and available. Well, this was the case
for some entity childs (those i touched) but not for some other entity childs. So I really asked myself what’s happening here and why gae tells me about
these crappy Nullpointerexceptions. So please remember: When you want to retrieve entity childs, make a “touch” (via the getters) on every entitychild OR,
and this solution I choose, tell the JDO datastore to fetch the childs automatically once the parent entity is called. You can do so by extending the
@Persistent annotation to @Persistent(defaultFetchGroup = “true”) :)

Introducing a Data Access Layer

The code at the “front” when receiving a Restcall was quite difficult to read because it handled the JaxRs part, the JaxB conversion and the jdo part too.
By introducing a simple Data Access Layer the code on these places is now shrunked a lot :)
So by reengeneering the Server part a little (which should be finnished tomorrow) i hope the whole thing will work better :)

Deployment

To test your application after Deployment you need a litte patience :D why?
This has something to do with the way of how google app engine provides the opportunity to query your data.
Read here to learn more.
[...]The App Engine datastore maintains an index for every query an application intends to make. As the application makes changes to datastore entities,
the datastore updates the indexes with the correct results. When the application executes a query, the datastore fetches the results directly from the corresponding index. [...]

So…the first time you deploy your application with a new custom index, you need to wait for the index to finish building. This is sometimes a slow process, since new indexes go into a queue with everyone else’s new indexes. So this is what i am doing right know. Waiting for the Google App Engine finishing building my indexes, to test if the application works on the app engine.

Xml Validation

I used DTD files for simple xml file validation and referred to it in the DOCTYPE tag of the xml file. For some security reason the google app engine was not able to access the *.dtd files which were located at the war folder. I ended up with the fact that it is not possible to access these files out of the box with the java xml framework. Again this works very well on localhost but not at the GAE. Reading out these files must happen with Java IO file stream manually. Moreover i am validating my xml files not against DTD anymore, but against XSD files, because these are more flexible. For validation purpose i created a new class called XMLValidator which is able to validate and parse xml files in one breath. Here is the responsible code:

	public Document parseAndValidateXml(InputStream input, String xsdFilename) {
		StringBuilder sb = new StringBuilder();
		try {
			BufferedReader in = new BufferedReader(new FileReader(xsdFilename));
			String str;

			while ((str = in.readLine()) != null) {
				sb.append(str + "\n");
			}
			in.close();
		} catch (IOException e) {
		}

		String xsd_content = sb.toString();
		SchemaFactory schFactory = SchemaFactory
				.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		Schema sch;

		try {
			sch = schFactory.newSchema(new StreamSource(new StringReader(
					xsd_content)));

		} catch (Exception se) {
			throw new IllegalStateException("No Schema : " + se);
		}

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		factory.setSchema(sch);

		DocumentBuilder builder;
		Document document = null;

		try {
			builder = factory.newDocumentBuilder();

			builder.setErrorHandler(new ErrorHandler() {

				@Override
				public void error(SAXParseException e) throws SAXException {
					System.out.println(e.getMessage() + " ERROR");
					validation_success = false;
				}

				@Override
				public void fatalError(SAXParseException e) throws SAXException {
					System.out.println(e.getMessage() + " FATALERROR");
					validation_success = false;
				}

				@Override
				public void warning(SAXParseException e) throws SAXException {
					System.out.println(e.getMessage() + " WARNING");
					validation_success = false;
				}

			});
			document = builder.parse(input);

		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return document;
	}

This method takes the InputStream of the XML file (which came across the webservice), the filename of the corresponding *.xsd file and produces a Document Object representing the wellformed and validated XML file, if everything was fine!

See you in my next post on which we continue with android :)

cheers,

bernd

, , , ,
  • Delicious
  • Facebook
  • Digg
  • Reddit
  • StumbleUpon
  • Twitter

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>