Sunday, December 13, 2009

Upgrading to GWT 2.0 with GXT 2.1.0

I had to upgrade my GWT version to 2.0.0 with GXT 2.1.0. For the most part this was pretty straight forward. One change that impacted me was the usage of ImageBundle being deprecated. To convert it to the GWT version of doing things I had to do the following:
  1. extend com.google.gwt.resources.client.ClientBundle instead of ImageBundle
  2. replace @Resource with @Source (from ClientBundle)
  3. the return types will need to change to com.google.gwt.resources.client.ImageResource for each of the image methods.

Instead of using the interface directly (after being runtime binded with GWT.create()), you will need to convert the ImageResource to an AbstractImagePrototype. This can be done by calling the create(ImageResource) method.

The thing that is unfortunate about this, is all my setIcon() calls simply referred to a singleton instance of the images. Now they all need to convert to via the create() call. Hopefully I can work out a nicer solution for the future.

The article that helped guide me in this came from the google wiki: ImageResource

Version Info
GXT: 2.1.0
GWT: 2.1.0

Friday, December 11, 2009

GXT 2.1.0 Conversion

The following is a list of the issues I ran into when I converted from GXT 2.0.1 to GXT 2.1.0. This is not the complete exhaustive list, however these may provide others with some of the workarounds.

  1. My dialogs will cascade events to the form panels and their contents on the dialog. A change was made to Layout which requires all components which are receiving the event to have a layoutData defined. Since dialogs would normally not hold a layoutData (in my case they were using FitLayout which results in a null layoutData), I had to change the cascading to start at the dialog's FormPanel.
  2. All text input components have the wrapper set to the id used to create the component (this should be a <div/> tag). The physical input field now has a "-input" added to the end of the id. This impacted my Selenium tests.
  3. The StoreFilterField required the setProperty("name") to be called in order for the filtering to actually be invoked. I also changed my overloaded applyFilters() method to be similiar to the super method in the way it adds/removes the filter on the store.
  4. @Override
    protected void applyFilters(Store<ModelData> store) {
     if (getRawValue().length() >= 3) {
      store.addFilter(filter);
         store.applyFilters(super.getProperty());
        } else {
         store.removeFilter(filter);
        }
    }
  5. In my country ListView, when the Events.Select was raised I was retrieving the selected countries from the selection model. This either changed or I was doing it incorrectly, as now the selection model was returning the items before the selection is registered. Instead, I switched to use the getIndex() of the ListViewEvent to find the country that was selected.
  6. For my image panel, I was using a GWT HTML component. This now required the parent to implement HasWidgets interface, which the ContentPanel in GXT doesn't (since all GXT components extend Widget from GWT). Fortunately there is a GXT component Html which does pretty much the same as the GWT one, and converting to use this worked.
  7. Nodes in a TreePanel had their rendering changed from a <li> tag to a <div> tag. This impacted Selenium tests.
  8. Popup menus changed from using <li> tags to using <div> tags. This impacted Selenium tests.

Overall, the changes took me approximately 5 hours to incorporate and resolve the differences in my selenium tests. Some of it was due to changes in the rendering of the GXT components (which is to be expected and is not difficult to reconcile) and some of it was related to event sequencing and component model changes. It was these later changes which impacted my time the greatest.


Version Info
GXT: 2.1.0
Selenium: 1.0.1

Saturday, November 7, 2009

Civilization 4 on Windows 7

If you install and attempt to run Civilization 4 on Windows 7 you will likely receive an error similiar to the following:

I was able to resolve this by downloading and installing the latest released runtime version of DirectX. I suppose if you install and play many games you likely have a newer version of the DirectX runtime, but this game was my favorite and was the first (and currently only) DirectX game I am running under Windows 7.

Saturday, June 6, 2009

Pygments for Source Highlighting

I mentioned to a colleague a week ago that I wanted to provide better syntax highlighting of source code in my blog entries. He suggested I look at Pygments which is a "generic syntax highlighter for general use in all kinds of software such as forum systems, wikis or other applications that need to prettify source code.". I have to admit, I kind of like it and it is relatively easy to use (just make sure you use spaces in your code instead of tabs!

Take a look: http://pygments.org.

Friday, June 5, 2009

GXT 2.0 and Selenium - Part 1

For those of you who follow the GXT toolkit know, they are currently in the process or preparing for the release of the 2.0 version. I converted to the 2.0 M1 version a few weeks ago and other than a few issues, have been able to continue using my application (and building on it). However when I upgraded to the 2.0 M2 version, I had several key areas that no longer worked. Of course, while I had unit tests to test my services, I didn't have anything for my GWT-based client. At this point I rolled back any updates I had made to be compliant with 2.0 M1, and started to write some Selenium tests to cover some of the key functionality. This should help my conversion to 2.0 M2 later. Through the use of Selenium I have come across a few tips and techniques I thought I'd share:

1. Be liberal with pauses (just be smart about it!)
Ideally you should be able to type, click and type, but the nature of GXT being a web application means that there are many transitions that occur, elements need to be built/loaded etc. Do not assume that after clicking an action to show a dialog that the dialog is immediately there. To handle this I do two things: First, ensure that the element is present, and second that the element is visible. Since the element may take a while to materialize you should wrap this in a loop for a predetermined time and break when both conditions are met (I generally use 1.5-10.0 seconds as the maximum timeout waiting 100-250ms between checks). You need to use your judgement based on the complexity of the elements you wait for (for example updating a status bar may be immediate, but creating a complex form (for the first time) might require creation of models etc.) You need to check for the element being present first, because the call to selenium.isVisible( ) will throw an exception if the locator is not yet in the DOM. Here is a simple example from one of my Selenium solutions:
for(int i = 0; i < 10; i++ ) {
   if( selenium.isElementPresent(itemLocator) && selenium.isVisible(itemLocator)) {
      selenium.mouseDown(itemLocator);
      break;
   }
   SeleniumHelper.pause(250);
}

2. Keystrokes and GXT
For text input, Selenium provides two methods: type() and typeKeys(). The later supposedly emits keystroke events as the keys are typed in sequentially (whereas type() acts more like a paste of a set value). As I posted previously in Selenium with GXT..., the problem with these methods and GXT is they do not seem to play very well together. I have not done too much data entry testing yet in Selenium, but I have cases under test and only one of the three worked using type() without changes. The two that didn't work consisted of a StoreFilterField to filter my tree view, and the other were simple form fields in a window.

For the StoreFilterField, it was essential that as each keystroke was made appropriate events were fired to cause the filtering to be invoked. In my case, it wasn't important to have the events be emitted with each keystroke, just when I was done. What I discovered was that I had to manually emit the events after typing with a slight delay after the keys had been typed. From running these tests over and over, it would appear that a delay of approximately 250ms is sufficient between the typing and the event emitting. Keep in mind, if you use typeKeys( ) this is supposedly already emitting these events. What is important is to emit them again. This is what seemed to trigger the filter to fire. Within Firefox, you need to emit three key events: keydown, keypress, keyup in that order. As well, as I will discuss next, form field were only populated in GXT with a blur event, so I also fire the blur, focus events. While this might seem kind of over-complex, it does work, and my tests have been running smooth (and passing) since. I wrote a method which I put into one of my abstract solutions called textWithEvents. Lets look at the code:
public void textWithEvents( String locator, String text ) { 
    for( int i = 0; i < text.length(); i++ ) {
        selenium.type(locator, text.substring(0,i+1));
        fireKeyEventSequence(locator);
        SeleniumHelper.pause(25);
    }
    SeleniumHelper.pause(225);
    fireKeyEventSequence(locator);
}

protected void fireKeyEventSequence(String locator) {
    selenium.fireEvent(locator, "keydown");
    selenium.fireEvent(locator, "keypress");
    selenium.fireEvent(locator, "keyup");
    selenium.fireEvent(locator, "blur");
    selenium.fireEvent(locator, "focus");
}

Now one thing you'll note is that I am using type() and I am actually re-typing each character. I could have typed the whole thing, but then this would not have fired the events as I was typing (which some code may require). But why not typeKeys? I can not explain this yet, but typeKeys() leads to invalid strings not matching the input text. I had a test failing over and over for a while and it was because of the use of typeKeys() in a StoreFilterField. What was happening was while trying to type in the text "My Test_233333--2", the result was "MTest_233333". Somehow typeKeys() was dropping characters or invoking other characters (such as a backspace) instead. I was at a complete loss. When I came across this in disgust (having lost almost an hour trying to figure out the problem - I thought it was related to locators originally) I decided to switch to type() even though it is a little slower. If you are filling out simple forms you will not really notice more than a few extra milliseconds. For typing large amounts of text in a text area, I would recommend a hybrid of the above method, likely simply using type() for the entire text and then double emit the key events with a pause between (unless you need to test UI interaction with each keystroke).

Finally, the reason for the blur and focus events was to ensure the form fields were populated. In GXT, form fields like TextFields do not store their value in the input HTML components, but internally (I assume as a variable in Javascript). You can see this watching the changes to the DOM using Firebug with Firefox. For this reason, to ensure the values are updated firing the blur event, will update the GXT component value. The focus event was fired just to maintain focus in the component.


I intend to continue this topic to cover some other areas I have discovered (such as smart locators and ComboBoxes) in an upcoming article. I felt this article was getting a little long. Stay tuned!


Version Info
GXT: 2.0-M1
Selenium: 1.0-beta2

Thursday, May 28, 2009

Selenium with GXT: getting textfields to emit those key events

In my Stamp Editor I have a tree browser which can browse collections, albums and countries. Directly above this, I have a StoreFilterField in which I can type text to filter the tree. I wanted to write a few selenium tests for this functionality to verify the items are found. The problem I ran into is when I told selenium to type the text, the text would appear but the filter would not get invoked. I knew this had something to do with the events being emitted so I tried to figure out what was going on. It turns out, it appears to be a timing issue. A great link which discusses the Javascript events (and browser differences) is here. Since the only selenium browser I am supporting for now is Firefox 3.X, the events I needed to emit to tell the textfield to start filtering was:
  1. keydown
  2. keypress
  3. keyup

The problem was, is even after emitting these events, the filtering was not getting invoked. After playing around in Firebug, I discerned that I needed to "refire" these events after a point of time. I wrapped this into a common method of my selenium solutions such that the code now looked like this:

public void textWithEvents( String locator, String text ) { 
   selenium.typeKeys(locator, text);
   SeleniumHelper.pause(500); // give events time to breathe
   selenium.fireEvent(locator, "keydown");
   selenium.fireEvent(locator, "keypress");
   selenium.fireEvent(locator, "keyup");
}



Version Info
GXT: 2.0-M1
Selenium: 1.0-beta2

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>

Wednesday, February 18, 2009

JPQL and Upper case queries in LIKE

I had a situation where I needed to write a query which would perform upper case comparisons in a LIKE statement. It took me a while to figure this out, mainly because I didn't realize the right-side of the LIKE statement does not support any of the functions. So given a query like this:

  SELECT name FROM Countries WHERE name LIKE '%someValue%';

to write this in a valid JPQL format (assuming we have a persistent bean Country with an attribute name, you would write it out as follows:

  String searchExp = "find me";
  Query qs = entity.createQuery("SELECT c.name FROM Country c WHERE UPPER(c.name) LIKE '%:val%'");
  qs.setParameter("val",searchExp.toUpperCase());

The key here is to convert the right-side in code and then you can use the function UPPER( ) for the left-side of the expression.

This was tested with MySQL and HSQLDB with EclipseLink. There was an article I found here which states that with MySQL 5.1 onward you don't need to use the LOWER function, but I have not verified this yet (nor found the collaborating evidence on MySQL's website). Running against my test system in HSQLDB (in memory) it did not find the results in my unit tests.