Thursday, March 26, 2009

Using JSON with JAXB in new Jersey 1.0.2

Jersey 1.0.2 was released in early February and I just got around to updating to it. I was quite excited to read about the new support for JAXB marshalling to JSON formats (this was introduced I believe in an earlier release but not well detailed). Jakub Podlesak has some nice articles on this functionality on his blog and would recommend reading them. One thing I found, is initially I attempted to use the MAPPED_JETTISON notation in the JSONConfiguration which worked fine with Java JDK 1.6u10. However when I changed this to Natural notation to support my GXT application expected output, I recieved the following error:

javax.xml.bind.JAXBException: property "retainReferenceToInfo" is not supported 
   at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:63) 
   ...


Upon re-reading the dependency notes of Jersey, I noticed the following note: "This module depends on the JAXB reference implementation version 2.1.10 or greater, and such a version is required when enabling support for the JAXB natural JSON convention..." . The version of JAXB shipped with JDK 1.6 is not at a high enough level to support this functionality. Fortuantely the workaround to get this to work is pretty easy if you following the following steps:
  1. Download the JAXB jar from the Jersey depenendencies: jaxb-api-2.1.jarand save this to a local location.
  2. Copy the jaxb-api-2.1.jar to the jre/lib/endorsed folder of your JRE or JDK installation. You may need administrative privileges on some platforms.
  3. Restart eclipse (or other IDE).
  4. In your project class path, include the other JAXB jar files listed under the "non maven developers require... section of the JAXB portion of the document

Information on the endorsed libraries is available here.

Saturday, March 14, 2009

Referencing keys of objects in db.Models

The Google App Engine revolves around keys. If you have references to other objects within your Models, it is important to understand the consequence of accessing the model (to prevent fetch statements). In particular, if you only need to Key of the item (or an attribute on the Key such as the id()) then you want to avoid inflating the persistable. There are numerous suggestions on how to accomplish this. Squeeville posted a nice short explaination of how to do it here.

Tuesday, March 10, 2009

GWT and Google App Engine - An Update

In my previous post GWT and Google App Engine - How to Develop! I outlined an approach one could take to develop a GWT application using the Google App Engine (either from the outset or partially mapping services to GAE over time). In the article I recommended the usage of the HttpRedirectFilter. While this filter worked well using the GAE SDK, I ran into problems connecting to google's remote hosts. In particular, the filter was returning 302 status codes (Temporarily Moved) on the redirect, which AJAX will not treat as a successful outcome (AJAX requires 200-series status codes for successful responses). Instead, I decided to simply write my own filter based on similiar design outlined in the book "GWT Web Toolkit Applications" written by Ryan Dewsbury (ISBN-13: 978-0-321-50196-7). While this book is written against GWT 1.4 (and prior) it is a great reference for developing applications for GWT. There may be newer editions of the book and I would recommend it it.

If there is interest in the filter, I suppose I could post it to the blog or a source repository as open-source under Apache 2.0 License. I did run into a few tricks that go beyond what is highlighted in the GWT book which are worth noting (some are specific to forwarding to GAE, some are general "advanced" WEB related)
  1. GZIP encoding. If the response from the host (GAE or other) has a Content-Encoding header set containing gzip you will need to use a GZIPInputStream( ) to parse the input or error streams from the response. By default, the GAE SDK was not returning GZIP output, and my results were fine, until I ported my python app to GAE servers. At this point the response came back in gzip thus resulting in garbage data without the GZIPInputStream.
  2. The proxy as defined in the book proxies from Source A to Host B. In my case, I wanted some more advanced functionality (like mapping partial or complete URIs to a new URL) so implemented a simple redirectMappings.xml property file to do this.
  3. For example, in a Restful Web application, you might have a resource path like /resources/preferences/categories/currency where the resource is preferences and the remaining URI values are directing the request (in this case getting all preferences with the currency category). Ideally you do not want your mapping to be setup against all possible URIs, but only the resource path (/resources/preferences in this case) appending the remaining URI path to this redirected URL.
  4. The example proxy does not encode the form data in the proxy (and assumes you are encoding it in your client under a "post" attribute). My approach was to treat the requests from GWT no different than any application request, so any values like method, FORM data should be encoded into the headers/parameters rather than having the proxy except some specialized structure of data. This makes the proxy "benign" in nature and it also means that it does not really matter if the proxy is there or not (from the client side).
  5. FORM data should only be added if the request is a POST, PUT or DELETE request. (although in REST, the DELETE should be a path variables on the URI) GAE will return a status code of 500 if the GET request contains FORM data.
  6. GAE will reject requests which contain certain headers. I have had difficulty getting information from the Google site on this, but from the discussion forums (as well as my testing) requests which contain the following were rejected:
    • CONTENT_LENGTH
    • DATE
    • HOST
    • REFERER
    • VARY
    • VIA
    • X_FORWARDED_FOR
    Again, this is an unconfirmed list. This list was pulled from two discussion threads against issues filed against GAE (Issues 198 and 342).


I also thought I should make a brief commentary on the overhead associated with using a servlet filter for redirects. It would appear that using the filter imposes ~ 400-500 ms overhead per request. This is probably not a big deal on development systems, but obviously I would not recommend this for production. My suggestive approach in this article (and former) are really meant to be used for a developer to build an application concurrently with GWT (using the Hosted Mode browser) in conjunction with the GAE SDK (or even hosted server(s)). This eliviates the pain of having to have a fully functioning service/server prior to developing the client and allows each to be developed concurrently making a much cleaner development experience (especially if you are like me and doing this as a hobby).

Sunday, March 1, 2009

GWT and Google App Engine - How to develop!

So I have developed an application in GWT using the GXT library which is currently connecting to a Restful WebService through Tomcat and using JPA to access my MySQL Database. I recently had a disk failure on this system, and so have become acutely aware of the possibility at some point I might want to have my application hosted.

I was looking at the Google App Engine, and wanted to experiment with it. The problem is, there are blogs talking about putting your GWT application onto a GAE app, but how do you develop the app on your local box and communicate with either a local or remote GAE application? You can develop the GAE in eclipse and run it locally, but there is currently no way to embed GAE apps in your hosted mode browser for GWT. As well, by default the GWT app sandbox does not allow you connect to a site outside of the site hosting the GWT app. My requirements were simple:
  1. Develop a GAE application in Eclipse and run the server locally.
  2. Continue to develop my GWT Application in eclipse connecting to my existing server.
  3. Be able to connect my GWT Application to a GAE application, with the intent to later deploy it on that application (therefore request url should remain the same).
  4. (Optionally) - "replace" a web-service running on my server with a GAE application service.

The way to do this, is to insert a redirect filter in the embedded tomcat run within the GWTShell to send any requests matching a particular syntax to the GAE application. This actually worked surprisingly well. The filter I am using was one I found after a quick search, I came across the HttpRedirectFilter. This didn't take much at all to configure and voila I am off to the races. The general strategy here, is you can use this redirect filter to forward requests to the GAE application while in development. Upon compilation of your GWT application you can bundle it with the GAE application (see Configuring Eclipse on Windows to Use With Google App Engine) and deploy this to Google. In my case, I can still have features hosted locally and as I convert a Restful Resource to GAE I can use the Redirect Filter to redirect the request to GAE. Once everything is converted, I can stop supporting my Jersey-based application and use the pure GAE app. At this point, I am purely in the evaluation stage of GAE, but it was a non-starter if I was not going to be able to concurrently develop a GWT and GAE applications together. This method gives me this ability to experiment with this. As well, you could concievably use this technique to develop a pure GAE application, by just providing the redirect filter in your web.xml configuration.

As an example of the redirectfilter.xml I am using, I configured a new fictious resource testpy to be redirected to my helloworld GAE application on port 9998 on my local machine. Since I had to read the source code provided in the HttpRequestFilter to get this to work, I figured I would show what my file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE redirect-filter PUBLIC "-//zlatkovic.com//DTD RedirectFilter 2.0//EN" "http://www.zlatkovic.com/dtd/redirect-filter-2.0.dtd">
<redirect-filter>

 <redirect match="/StampWeb/resources/testpy$" target="http://localhost:9998/helloworld" remote-address="127.0.0.1/255.0.0.0"/>
 
</redirect-filter>


My web.xml configuration look like the following (Note: I am currenly filtering everything, but you could easily configure it just for the resources that are on the GAE application):

   <filter>
        <filter-name>HttpRedirectFilter</filter-name>
        <filter-class>com.zlatkovic.servlet.RedirectFilter</filter-class>
        <init-param>
         <param-name>configFile</param-name>
         <param-value>/WEB-INF/redirectfilter.xml</param-value>
        </init-param>
        <init-param>
         <param-name>reloadConfig</param-name>
         <param-value>true</param-value>
        </init-param>
        <init-param>
         <param-name>logRedirects</param-name>
         <param-value>true</param-value>
        </init-param>
   </filter>
   <filter-mapping>
     <filter-name>HttpRedirectFilter</filter-name>
     <url-pattern>/*</url-pattern>
   </filter-mapping>