Showing posts with label GWT. Show all posts
Showing posts with label GWT. Show all posts

Wednesday, August 21, 2013

JSON parsing in JavaScript

Recently I've has some blocking issues with some code I wrote a while ago. A colleague tried to re-use that code with a different back-end and he kept experiencing the exception:
JSON.parse: unexpected character
Using Firebug, I promptly inspected the JSON content that was retrieved from the new service and by copying and pasting it into http://jsonlint.com/ it seemed to be valid JSON. However, the exception was still there and clearly indicated an issue with the format of the incoming content. I therefore inspected the code of both client and server and it turns out that (1) the old JavaScript snippet was using the eval function and (2) the new back-end, mimicking what my old testing code was doing, was generating through a servlet some testing JSON just by concatenating some strings and serializing the results as JSON.

The serialization of the service was including some '\n' (new lines) that, in the old ecosystem, improved the visualization of the JSON content apparently without disrupting the activity of the eval function. The serialized content included also some dates in the format 'MM/dd/yyyy HH:mm:ss Z'.
The eval function invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure (read more on json.org).
Strangely the same code that was working fine in my configuration, was failing in the configuration used by my colleague that seemed failing while interpreting the format of the dates.

As I had a similar problem months ago, I've decided therefore to move away from the eval function:
    In the old GWT code, making use of JNI:

    public static native JavaScriptObject parseJson(String jsonStr) /*-{
        return eval('(' + jsonStr + ')');
    }

    The equivalent in pure JavaScript would be (remember the parenthesis 
    as they turn the code into an expression that returns, rather than 
    just code to run):

    function parseJson(jsonStr) {
         return eval('(' + jsonStr + ')');
    }
to use the more recent JSON.parse which provides validation of the JSON content unlike eval that is faster but allows the string being parsed to contain absolutely anything including function calls.
Native JSON support is included in newer browsers and in the newest ECMAScript (JavaScript) standard. Similar features were already available with some JS libraries such as JQuery (http://api.jquery.com/jQuery.parseJSON/).
See http://www.w3schools.com/json/json_eval.asp for browser and software support.
When using the JSON.parse it is however necessary to escape the control characters.
According to section 2.5 of the JSON spec at ietf.org/rfc/rfc4627.txt: "All Unicode characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F)."
In that specific testing case the newline character could have been present in both the JSON values and in between JSON elements.
    // 1) Example of JSON with newline in the value
    [{"name":"Paolo Ciccarese \n"}]

    // 2) Example of JSON with newline between elements
    [\n{"name":"Paolo Ciccarese"}]
The above case 1) can be addressed by escaping the content (for instance replacing '\n' with '\\n'. The case 2) is illegal in JSON and would work only if using the eval function.
In my case the servlets were generating the '\n' because of the use of out.println instead of the harmless out.print
So in my case the parseJSON function became:
    In the old GWT code, making use of JNI:

    public static native JavaScriptObject parseJson(String jsonStr) /*-{
        try {
            var jsonStr = jsonStr      
                .replace(/[\\]/g, '\\\\')
                .replace(/[\/]/g, '\\/')
                .replace(/[\b]/g, '\\b')
                .replace(/[\f]/g, '\\f')
                .replace(/[\n]/g, '\\n')
                .replace(/[\r]/g, '\\r')
                .replace(/[\t]/g, '\\t')
                .replace(/\\'/g, "\\'");
            return JSON.parse(jsonStr);
        } catch (e) {
            alert("Error while parsing the JSON message: " + e);
        }
    }-*/;

    In pure JavaScript would be:

    function parseJson(jsonStr) {
        try {
            var jsonStr = jsonStr      
                .replace(/[\\]/g, '\\\\')
                .replace(/[\/]/g, '\\/')
                .replace(/[\b]/g, '\\b')
                .replace(/[\f]/g, '\\f')
                .replace(/[\n]/g, '\\n')
                .replace(/[\r]/g, '\\r')
                .replace(/[\t]/g, '\\t')
                .replace(/\\'/g, "\\'");
            return JSON.parse(jsonStr);
        } catch (e) {
            alert("Error while parsing the JSON message: " + e);
        }
    }
  
Therefore in the case:
    [{"name":"Paolo Ciccarese \n"}]
the newline is not interpreted as a newline in the JSON source anymore but as a newline in the JSON data, which is perfectly fine.

In conclusion, I am still not sure why the dates interpretation was failing with the eval method. But with the JSON.parse approach the problem is gone.

I also found this: 'A fast and secure JSON parser in JavaScript'. I did not have time to check out yet but it is promising: ' does not attempt to validate the JSON, so may return a surprising result given a syntactically invalid input, but it does not use eval so is deterministic and is guaranteed not to modify any object other than its return value'.

Wednesday, May 09, 2012

Running GWT 2.4.0 with STS 2.9.1 and Grails 2.0.3

Alright, if you followed all the steps of the previous post, you should be able to see the results of the GWT code execution at the address:
http://localhost:8080/{projectname}/hello.gsp 
As you might have noticed, I previously asked the plugin to compile the GWT code (compile-gwt-modules). That operation takes some seconds as the entire artifact is recompiled (when the application will grow, the compilation can last minutes).  Luckily there is an alternative, the hosted mode. When an application is running in hosted mode, the Java Virtual Machine (JVM) is actually executing the application code as compiled Java bytecode, using GWT plumbing to automate an embedded browser window. This means (1) we don't need to recompile the code as STS is producing the Java bytecode for us incrementally (2) the debugging facilities of your IDE are available to debug both your client-side GWT code and any server-side Java code as well.

First we start the grails application (run-app), second, in the command prompt we type:
run-gwt-client
This last command starts the hosted mode and you should see appearing a window like the one depicted in figure 1. 

Figure 1: hosted mode window.

Now we can 'copy to clipboard' and open that link in a web browser:
http://localhost:8080/GwtTest/hello.gsp?gwt.codesvr=127.0.0.1:9997
The page should appear in the window and the alert 'hello' should display. Now you can verify the usefulness of the hosted mode by updating the alert - in the class HelloApp.java from 'hello' to 'hello me' - and reloading the page. The alert will display the new string without you having to trigger the GWT code compilation manually. And this will result in a huge save of time. (Read more)

Note. Remember that the manual compilation is still necessary prior to deployment as the deployed version of the page will run the compiled JavaScript.


Friday, May 04, 2012

Setting up STS 2.9.1, Grails 2.0.3 and GWT 2.4.0

If you need to integrate Grails and Google Web Toolkit (GWT) here is a list of tips. If you are interested in Grails you might want to consider the SpringSource Tool Suite or briefly STS. I usually install the STS package in a directory which name includes the version of the STS software to make sure multiple versions of the tool can beautifully coexist on the same machine. The tool is currently in version 2.9.1 and, as the previous versions of STS, it offers a good set of features for integrating with Grails. After the installation is completed I suggest to open the Dashboard and select the tab "Extensions". If you have just installed the tool, it should look more or less like in figure 1.

Figure 1: STS 2.9.1 Dashboard right after installation.

As you can easily verify in figure1, I would suggest to pick two extensions in particular: Grails Support and Google Plugin for Eclipse - which now comes with GWT 2.4.0. Select those and proceed with the installation. I don't usually pick the "Grails (current production release)" as I usually download and install Grails separately. The current release version of Grails is 2.0.3 and you should download it and unzip it in a convenient location.

Figure 2: Setting up Grails in STS.

Once the installation is terminated, it is time to configure the plugins. The Grails Support plugin needs to know where the Grails installation is (figure 2). We can now create a new Grails project that I am going to name GwtTest.

Figure 3: Creating a new Grails project in STS 

The creation process should ask you if you want to change the perspective into the Grails perspective offered by STS. Once the project is created it is time to install the GWT Plugin for Grails.

Figure 4: Opening the Grails command prompt

You can perform this operation through the Grails command prompt offered by STS (figure 4) by typing
install-plugin gwt
And the process should complete displaying the details in the console:

Figure 5: Console after installation of the GWT plugin (0.6.1) for Grails
 
Note: Remember also to set up the GWT_HOME that is used for compilation.

We are now ready to create our first GWT module (learn about GWT modules here). Using once again the Grails command prompt offered by STS, we type:
create-gwt-module org.example.HelloApp
Once the process is completed, if you refresh the project, you will be able to notice that a new directory 'src' has appeared in the project explorer.

Figure 6: Project explorer and Console after the creation of the HelloApp GWT module

In order to declare this folder as a source code folder we can right click on the project and select 'Build Path'>'Configure Build Path' dialog. In the tab 'source' we select 'add folder' and we pick the newly created 'src/gwt' folder.

Figure 7: Declaring the GWT folder as a source code folder

We can now create the page hosting the GWT script by typing in the command prompt:
  create-gwt-page hello.gsp org.example.HelloApp
The new page will include the line of code that is performing the actual import of the GWT artifact:
<script src="${resource(dir:'gwt/org.example.HelloApp',
 file:'org.example.HelloApp.nocache.js')}" type="text/javascript">
</script>

We are now going to modify the HelloApp.java file adding Window.alert("hello"); within the method onModuleLoad() so that when the script is loading the alert 'hello' will fire.

We then compile the GWT code by typing in the command prompt:
compile-gwt-modules
And we are potentially ready to go. After running the Grails project - a simple run-app is good enough - and opening the page:
http://localhost:8080/{projectname}/hello.gsp
you will notice that nothing happens. As a matter of fact, if you check out what happens with Firebugs, you will notice that a resource has not been found. Unfortunately, it seems the Grails Resources Plugin, which is installed by default in the project, is not compatible with the Grails GWT Plugin. As suggested in this post we can modify the Config.groovy file to include:
grails.resources.adhoc.excludes = ['**/gwt/**']
When restarting the server, the hello.gsp page should now work and fire the 'hello' alert.

Wednesday, September 21, 2011

UIBinder, CssResource and CSS (GWT)

Few month ago I blogged about ClientBundle, UIBinder and CSS (GWT). I just realized that an important use case was missing. And here it is.

4) Using CssResource for CSS expressed in the UIBinder. When creating a UI with the UIBinder it might happen to include some CSS rules in the ui.xml file.

<ui:UiBinder
  xmlns:ui='urn:ui:com.google.gwt.uibinder'
  xmlns:g='urn:import:com.google.gwt.user.client.ui'>

    <ui:style>
       .outer {
          width: 100%;
       }
    </ui:style>
    <g:SimplePanel ui:field='sideBar'>
    </g:SimplePanel>
</ui:UiBinder>

It is possible to refer to those CSS rules from the GWT code. For doing so we have to declare a 'type' for ui:style:

<ui:UiBinder
  xmlns:ui='urn:ui:com.google.gwt.uibinder'
  xmlns:g='urn:import:com.google.gwt.user.client.ui'>

    <ui:style type='org.example.Example.ExStyle'>
       .outer {
          width: 100%;
       }
    </ui:style>
   
    <g:SimplePanel ui:field='sideBar'>
    </g:SimplePanel>
</ui:UiBinder>


Now, in the class  org.example.Example, we can reference the CSS rules and use them:

public class Example extends Composite {

    interface Binder extends UiBinder { }    
    private static final Binder binder = GWT.create(Binder.class);
   
    @UiField SimplePanel sideBar;
    @UiField ExStyle style;

    interface ExStyle extends CssResource {
        String outer();
    }

    public Example() {
        initWidget(binder.createAndBindUi(this)); 
        sideBar.setStyleName(style.outer()); 
    }
   ...

Sunday, February 27, 2011

ClientBundle, UIBinder and CSS (GWT)

In a previous post I was discussing all the possible ways for using image resources with GWT. Another thing you might want to do is dealing with CSS.

1) Standard use of CSS. While using GWT you can certainly use the CSS how you would use them for any other application, simply declaring CSS classes in a *.css file and importing it in the webpage of interest. With GWT widgets you will then simply set the style name as follows:
widget.setStyleName("cssClassName");
This approach works, however, if the CSS declaration is missing no exceptions are raised. Also, if you use multiple CSS files as I do, it is always annoying to find the declarations when you need to.

2) Using the UIBinder. If you are already using UIBinder, the easiest way to include CSS declarations is to add them to the binder. It is easy and it is safe as the Eclipse plugin is helping you out in finding missing declarations. I always use Eclipse but if you don't I am assuming you'll still find the problems at compile time.
<ui:UiBinder
  xmlns:ui='urn:ui:com.google.gwt.uibinder'
  xmlns:g='urn:import:com.google.gwt.user.client.ui'>

    <ui:style>
       .outer {
          width: 100%;
       }
    </ui:style>

    <g:VerticalPanel styleName='{style.outer}'>
    </g:VerticalPanel>
</ui:UiBinder>
The downside of this approach is redundancy. Sometimes I want to use CSS declarations multiple times and, with this approach, I have to repeat them for each single Binder.

3) Using CssResource. Another alternative consists in doing something similar to what you can do for icons with ImageResource. First I declare the set of declarations of the stylesheet in a file that I name Commons.css:
.smallIcon {
    height: 16px;
    width: 16px;
}

Then, linking the CSS file, I declare the use of the stylesheet as a resource for the application:
public class Example implements EntryPoint {

  public interface Resources extends ClientBundle
  {
     public static final Resources INSTANCE =  GWT.create(Resources.class);
 
     public interface Resources extends ClientBundle { 
        @Source("org/example/application/client/Commons.css")
        CommonsCss commonsCss();
     }
     
     ...
  }
  
}
Now, where the dots in the above snippet are, I can declare the stylesheet declarations I want to expose to the application:
public interface CommonsCss extends CssResource {
     String smallIcon();
}
As the CSS class is named as the method everything works fine. However, sometimes you might want to change the name of the method. Using Java annotations you address that issue as well:
public interface CommonsCss extends CssResource {
     @ClassName("smallIcon")
     String smallIconClass();
}
Now, we can write something like:
Resources resources = Resources.INSTANCE.factory().create();
Image img = new Image();
img.setStyleName(resource.commonsCss.smallIcon());
...
This approach allows you to collect in one single place CSS declarations you need to use in multiple packages in your application. Also you can leverage a good amount of validation in your Java code. You might argue the process can be a bit tedious but I can assure you, for a big GWT application, it can help you saving lots of time later on especially when refactoring the code.

There are other interesting things to know about the ClientBundles, but for now I'll stop here.

Tuesday, November 09, 2010

UIBinder, CSS and Images (GWT)

I am working with GWT (Google Web Toolkit) since a while now. One of the things I am regularly doing (since version 2.0) is creating UIs through Declarative Layouts with UiBinder. While creating the ui.xml files it is normal to have the need of displaying images or icons.

1) Integrating background images with the ui:style section: for a long time have been using simple colors to create my look and feel but lately I started to feel the need to give the UI a better look using images as background. One way of getting this done with GWT is to include in the ui.xml file something like this - where the image is in the same folder of the ui.xml file:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>

  <ui:style>
    @url fileUrl bckImage;
    .titleBar { background: fileUrl repeat 0 0; }
  </ui:style>

  <ui:data field='bckImage' src='image.gif'/>

  <g:HorizontalPanel styleName='{style.titleBar}'>
  ...
  </g:HorizontalPanel>

</ui:UiBinder>

An alternative way:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>

  <ui:image field='gradient' src='image.gif' />

  <ui:style>
    @sprite .header {
      gwt-image: 'gradient';
      width: 100%;
      height: 18px;
    }
  </ui:style>

  <g:VerticalPanel>
    <g:HorizontalPanel ui:field='header' styleName='{style.header}'/>
  </g:VerticalPanel>

</ui:UiBinder>

2) Getting the images from the ClientBundle: in GWT it is possible to declare resources with something like the following:
package com.commonsemantics.example;

public class Example implements EntryPoint {

  public interface Resources extends ClientBundle
  {
     public static final Resources INSTANCE =  GWT.create(Resources.class);

     @Source("images/myIcon.jpg")
     ImageResource myIcon();
  }

  ...
}

Once the ImageResource is declared it is possible to use it in the ui.xml file:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>

  <ui:style>
    // This does not have any effect as the images are translated by GWT 
    // into background. In this configuration, in order to have the image 
    // of the right size, it has to be manually resized.
    .myImage { width: 18px; height: 18px; }
  </ui:style>

  <ui:with field='resources'
    type='com.commonsemantics.example.Example.Resources' /> 

  <g:HorizontalPanel styleName='{style.titleBar}'>
    <g:Image ui:field='rightSide' resource='{resources.myIcon}'  
      styleName='{style.myImage}'></g:Image>
  </g:HorizontalPanel>

  </ui:UiBinder>

3) Getting the images from the same package. When making use of images it is also possible to copy them in the same package of the class using them and refer to them as follow:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>

  <ui:image field='myImage' src='myImage.gif' />

  <g:HorizontalPanel>
    <g:Image ui:field='rightSide' resource='{myImage}'></g:Image>
  </g:HorizontalPanel>

</ui:UiBinder>