Dealing with Server Errors with RequestFactory

Request vs RequestContext

Only a Request will receive an invocation failure, not a RequestContext

GWT developers new to RequestFactory may get caught out by the fact that a RequestContext’s Receiver does not respond to server-side exceptions thrown while processing the request. A RequestContext will only receive constraint violations or general/transport failures.

It’s important to understand the difference between a Request and a RequestContext. A RequestContext allows you to bundle up multiple requests for more efficient data transportation – done by calling fire() from the RequestContext rather than from each individual Request. However as Thomas Broyer explains: “A RequestContext is not synonymous to a transaction … it’s more like a batching mechanism”. So when firing from a RequestContext you’ll still need to attach receivers to each individual request if you want to listen for server-side exceptions thrown during invocation processing.

Resending Request Data after a Server-Side Error

The procedure for resending data to the server differs according to the type of error:

  1. For constraint violations and general/transport errors (ie anything caught by RequestContext) – simply call fire() again
  2. For invocation failures – Create a new request context, copy the proxy’s values into a new mutable proxy and call fire() on the new request

GWT does not allow either a Request or RequestContext to be fired more than once, unless the RequestContext caught the error. Requests are locked and the proxies remain frozen and are only unlocked/defrosted in the case of a constraint violation/general failure to allow the application to resubmit its request.

Although it may seem like an oversight to not unlock a request after an invocation failure, Mr Broyer explains that this is by design. He explains that it is safe to unlock after a constraint violation, as bean validation is done before any invocations are processed, whereas an invocation exception may be thrown at any stage of the processing.

However, resending a request after an invocation exception may be necessary for common tasks such as checking that a value is unique. As bean validation does not handle this by default, this kind of validation check may be done during the invocation processing.  So for any validation done during processing, the only choice is to follow option #2; create a new mutable proxy and fire another request.

Copying a GWT Proxy

There currently exists no official way to automatically copy a GWT proxy. There’s an accepted issue – #5794 that tracks this much needed feature by proposing to add a RequestContext.copy() method. Copying a proxy can’t be done by simply cloning it; requests manage proxies by tracking changes made to them so that only the diffs are sent across the wire – not the whole object. To copy the values from a source proxy into a destination proxy, the destination must be made mutable (and therefore tracked).

There are 3 workarounds that are possible:

  1. Manually copy all the proxy values across to a new proxy
  2. Use the user-supplied workaround from issue #5794 to clone a proxy’s autobean – although apparently this only works for a ValueProxy or a simple EntityProxy with no nesting.
  3. Try out the patch for #5794 that’s currently being reviewed by Mr Broyer

Issue with Spring Roo

Developers creating applications based on Spring Roo’s GWT front
end must update the generated code to catch server failures

The developers from Spring have certainly been caught out – the GWT module for Spring Roo generates code that listens for failures on the RequestContext. Applications based on Spring-Roo’s GWT front end may be failing on the server and never reporting an error to the user. The front end merely navigates away from the edit screen and all data entry is then lost – the user none the wiser.

The solution is to update each save request to listen for server failures, which is relatively straight forward. If you want the user to be able to resend the data then it gets a little more complicated as the MVP design needs to be altered to accommodate the ability to create multiple requests (for example the CreateAndEditProxy activity is tied to a single request/proxy pair).

Posted in Uncategorised | Tagged , | Leave a comment

Running GWT applications as an IE HTA

Setting up a GWT application to run as a Microsoft Html Application (HTA) is not as straight forward as renaming the host page with a .hta extension. There are a couple of things we need to look at.

Chrome Frame Detection Bug

GWT 2.4 incorrectly chooses the Safari permutation for IE instances where Chrome Frame is merely installed but not enabled, meaning that GWT applications may/may not run with errors.

For HTAs (as tested on IE9) the problem is slightly different causing an error message to always popup. The bootstrap nocache.js fails to choose the Safari permutation (due to an exception thrown while attempting to load Chrome Frame), instead loading the IE permutation. Then once the permutation is loaded, the user agent detector starts returning Safari, causing an annoying popup to display:

“ERROR: Possible problem with your *.gwt.xml module file. The compile time user.agent value (ie9) does not match the runtime user.agent value (safari). Expect more errors.”

Issues with Frames

Frame Security

Out of the box GWT applications using an iframe permutations will not load, due to the requirement that all frames that form part of the application to have the application attribute set to “yes”. There are no plans to support this however Thomas Broyer suggests either using our own version of the nocache.js bootstrap template  or avoiding iframes altogether. The documentation describes how linkers are setup in your module XML file (under “Controlling compiler output”) however I’ve summarised it below.

Note that the iframe solution will not only allow you to target different IE user agents – IE9, IE8, Chrome Frame (once the bug is fixed) but to also split your code if you decide to host your HTA. If you’re not interested in either of these features then don’t worry about the hassle of enabling frames.

Removing Frames

Use SingleScriptLinker as the primary linker, done by adding the following to your module XML file:

<add-linker name="sso" />

Despite the name “add-linker”, there can be only one primary linker so this command will in fact replace the default primary linker “std”.

Note: The SingleScriptLinker doesn’t seem to include the loading of GWT themes so this you’ll have to do manually by adding a link in your host page.

Enabling Frames

Alternatively, to override an iframe linker, subclass the linker of your choice (IFrameLinker/CrossSiteIframeLinker) and overload the appropriate method that returns the bootstrap template’s path. Copy the template to somewhere in your classpath and add the following before the iframe is added to the document:

iframe.setAttribute("application", "yes");

Note: It must be an attribute and not a property, so doing iframe.application = “yes” will not work.

Then add the linker to the compilation process by using:

<define-linker name"ourlinker" value="your.version.of.IFrameLinker" />
<add-linker name="ourlinker" />

Packaging

When packaging for distribution, don’t forget to only compile the necessary permutations. If you’re requesting Chrome Frame then make sure to include both Safari and IE:

<set-property name="user.agent" value="safari,ie9" />

Rename the module.html to module.hta. Remember to remove the WEB-INF directory which will contain some sizeable jars that will unnecessarily increase the download size.

Packaging into a Self-Extracting Executable

Downloading a single file to run the application may be a better option for end users. The Microsoft tool, IExpress, generates self-extracting executables using the Cabinet archive format.

IExpress’ cab tool, makecab, does not extract into folders and will flatten the archive. You must either setup your application to run flattened or use your own archiving software on top of the cabinet (using something like 7zip which is LGPL licensed). The archiving binary will need to be added to the cabinet along with the archive in order for the client to unzip it again.

The application to run your HTA is mshta.exe. You’ll need to create a batch file to run it as it requires the absolute path to your *.hta host page and this may be retrieved from within a batch file by using the %CD% environment variable. The command to launch your batch file is:

cmd /c your_batch_file.bat
Posted in Uncategorised | Leave a comment

Multiple editors for a single peer domain object

Use @Path("") to descend into sub-editors without descending in the peer domain object map

Sometimes it may be useful to use split an editor up into multiple editors. A reason may be if you intend to use a TabPanel with each tab represented by individual UI binder templates. For each tab to participate in the editor hierarchy it must implement the Editor interface and be descendable from the parent editor.

The documentation explains that using different editors on the same path will help to solve this problem, but it requires the peer domain object to sit within another object.

This is where another new undocumented feature comes to the rescue: @Path("") Setting the path to an empty string indicates to the editor framework that it should not descend in the peer object map when it descends into the sub-editor.

Here’s a simple example:

public class Person {
    String firstName;
    String surname;
    String phone

    String preferredFruit;
    String preferredVegetable;
}

// A custom widget making use of TabPanel
ParentEditor extends Composite implements Editor<Person> {
    @Path("")
    ContactDetailsTab contactDetailsEditor;
    @Path("")
    PreferencesTab preferencesEditor
}

ContactDetailsTab extends Composite implements Editor<Person> {
    TextBox firstName;
    TextBox surname;
    TextBox phone;
}

PreferencesTab extends Composite implements Editor<Person> {
    ValueListBox<String> preferredFruit;
    ValueListBox<String> preferredVegetable;
}
Posted in Uncategorised | Tagged , | Leave a comment

Enums play nicely with ValueListBox

public enum Fruit {
    APPLE ("Apple"),
    BANANA ("Banana"),
    ORANGE ("Orange"),
    MANGO ("Mango");

    private String value;

    Fruit(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return value;
    }

    public static Fruit fromString(String value) {
        if (value != null) {
            for (Fruit fruit: Fruit.values()) {
                if (value.equals(fruit.toString())) {
                    return fruit;
                }
            }
        }
        return null;
    }
}

ValueListBox<Fruit> fruitPicker = new ValueListBox<Fruit>(new AbstractRenderer<Fruit>() {
    @Override
    public String render(Fruit object) {
        return object == null ? "" : object.toString();
    }
}
fruitPicker.setAcceptableValues(Arrays.asList(Fruit.values));
Posted in Uncategorised | Tagged , , | Leave a comment

Software Quality & Security

Today I read an article about how security consultant Patrick Webster stumbled across a serious security flaw within the First State Super’s members area of their site. First State’s irrational response by notifying the police and threatening legal action is a whole other story but what I also find interesting is the fact that these kinds of flaws happen in the first place.

Authentication & Authorisation

When logging into a website 2 very basic, yet fundamental, things need to happen to make sure that a site’s data is protected:

  1. A person needs to be able to prove who they are – known as authentication
  2. They must only be allowed to see information relevant to them – known as authorisation

This article explains the difference between the two in more depth.

First State’s Flaw

In First State’s case, the authentication seems to have been fine however the programmers implementing the site have obviously either forgotten about authorisation or perhaps, even worse, don’t understand the problem. I have worked with people who have written software with holes similar to this and didn’t understand until I demonstrated how easily I could circumvent their code.

The flaw centres around the server allowing authenticated clients to change an ID used by the software to retrieve records from the database. Changing the ID is quite simple as it appears in the page’s URL and is therefore just a matter of guessing a new one and substituting the original. Patrick was able to quickly whip up some software to retrieve a client list from the database by cycling through a range of IDs that the server would accept, which in this case would most likely have been as simple as a positive number.

At some point the software should have been executing authorisation checks by asking “Are you allowed to look at this?”. Making sure this is done for every entry point is a simple way to prevent this disastrous result.

Software Quality

These kinds of mistakes should never happen and is symptomatic of a software system written without basic quality checks. Too often though building quality software is ranked last in the list of priorities as quality has a cost and is not as easily tangible as things like bells and whistles.

Here’s a short, but not exhaustive, list of things that will improve the quality of software:

  • Hiring the right resources
  • Training
  • Reviewing software by peers
  • Paying off Technical Debt
  • Software testing

And finally if your data’s security is crucial and your software development team is inexperienced with security matters hiring an agency such as Patrick’s – OSI Security to audit your system may be well worth the investment.

Posted in Uncategorised | Leave a comment

Using orphanRemoval with Spring Roo

When using orphanRemoval=true on a collection in a Spring Roo project, the generated setter for the collection needs to be pushed in to use retainAll() rather than it being replaced.

Posted in Uncategorised | Leave a comment

Disabling selection for certain columns in a CellTable

I needed to add a column to a CellTable where the user was able to click on the cell to download a file, however I didn’t want the row to become selected. After looking at writing my own cell and overriding handlesSelection(), which seemed to disable the selection model altogether, I found a post by John LaBlanca where he describes how to disable SelectionEvents selectively.

He mentions that the selection events can be controlled by a DefaultSelectionEventManager. You can create an instance of this which has been set to ignore or trigger selection if certain columns are clicked. The instance is then passed along with your selection model into your CellTable.

Posted in Uncategorised | Leave a comment

Upgrading to GWT 2.3 with Roo

If you’d like to upgrade your Roo application to use GWT 2.3.0 there’s a couple of points that you’ll need to know:

  • GWT now requires that the source for javax.validation.api must be included. To do this add <classifier>sources</classifier> under the javax.validation.api dependency in your pom.xml.
  • 2.3.0 introduces a bug where validation errors are not shown for newly created entities. This is due to constraint violations from bean validation not being forwarded onto editors. An issue report suggests that it’s due to the parent proxy not being set on a violation object with the reporter supplying a suggested patch.
  • 2.3.0 allows you to set an empty row widget for CellTable so that you may show a message when there’s no data to display. Simply call table.setEmptyTableWidget(new Label(“No data”)) in your entity list view’s constructor.
Posted in Uncategorised | Leave a comment

Manual Event Firing

With jQuery:

$(target).dblclick();

With GWT:

DOMEvent.fireNativeEvent(Document.get().createDblClickEvent(detail,
  screenX, screenY, clientX, clientY, ctrlDown, altDown, shiftDown,
  metaDown), target);
Posted in Uncategorised | Leave a comment

Spring Security with GWT & Spring Roo

The following steps show you how to setup Spring Security with the GWT add-on for Spring Roo.  Note that Spring Security alone does not protect you from Cross-Site Request Forgeries (XSRF) – that requires the Roo generated code to make use of the new XsrfToken.

1. Setup MVC, Spring Security & GWT

When setting up the Roo application, make sure that security setup is run after a controller command. Eg:

  1. controller scaffold ‐‐class ~.Test
  2. security setup
  3. gwt setup

A dummy controller is created to force Roo to create a web tier – you may delete it and any corresponding components afterwards. If security setup is done after gwt setup without a controller command then components of the web tier do not get generated correctly. Also note that the web tier does not work in hosted mode.

2. Secure servlets

Secure any servlets you’ve setup – Roo uses RequestFactory:

<intercept-url pattern="/gwtRequest**" access="isAuthenticated()" />

3. Change the security entry point to return 403

Change the entry point to Http403ForbiddenEntryPoint so that a login page is not returned to the RPC mechanism. This entry point will return a HTTP status code of 403.

In applicationContext-security.xml:

<http ... entry-point-ref="http403ForbiddenEntryPoint">

In applicationContext.xml:

<bean id="http403ForbiddenEntryPoint"
      class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

4. Update GWT code to redirect to login

The 403 will cause RequestFactory to throw a RuntimeException.  Unfortunately RequestFactory only reveals the HTTP status code in the exception’s message (as at 2.3) so we have to examine the message for its presence.

From within ScaffoldDesktopApp, we can wait for a request exception in our uncaught exception handler:

public void onUncaughtException(Throwable e) {
  if (e instanceof UmbrellaException) {
    for (final Throwable e2: ((UmbrellaException) e).getCauses()) {
      if (e2.getMessage().startsWith("Server Error 403")) {
        Window.open("login", "_self", null);
      } else {
        ...
    }
  } else {
    ...
  }
}

5. Force default target

After authentication success, force the redirect, ie the target, to always use / so that Spring Security doesn’t try to redirect to /gwtRequest:

<form-login ... default-target-url="/" always-use-default-target="true">

Additional Configuration

Some people may also wish to secure the host html page as well which can be done with the standard security setup. Spring Security 3.1 allows the use of multiple http elements to configure a different filter chain for different parts of your application.

Posted in Uncategorised | Tagged , , | 15 Comments