Thursday, June 6, 2013

AutoBean - JSON to GWT Bean

GWT AutoBean Framework


                             The AutoBean framework provides automatically-generated implementations of bean-like interfaces and a low-level serialization mechanism for those interfaces. AutoBeans can be used in both client and server code to improve code re-use. For example, the Requestfactory system uses AutoBeans extensively in both the client and server code. This document describes the state of AutoBeans as found in the GWT 2.1.1 release onward.

This is quick start up article. See official article on Auto Bean for detailed information.

https://code.google.com/p/google-web-toolkit/wiki/AutoBean

Steps to integrate AutoBean

1) Create a POJO and corresponding interface
2) Create a AutoBean factory 
3) Encode or Decode JSON

AutoBean

An AutoBean must be parameterized with an interface type (e.g. AutoBean<Person>). This interface type may have any type hierarchy and need not extend any particular type in order to be usable with AutoBeans. A distinction is made as to whether or not the target interface is "simple."
A simple interface satisfies the following properties:
  • Has only getter and setter methods
  • Any non-property methods must be implemented by a category
A simple AutoBean can be constructed by the AutoBeanFactory without providing a delegate instance.
If a reference interface is returned from a method in a target interface, that instance will be automatically wrapped by an AutoBean instance. This behavior can be disabled by placing a @NoWrap annotation on the AutoBeanFactory.

POJO which used to encode or decode

// Declare any bean-like interface with matching getters and setters, no base type is necessary
interface Person {
  Address getAddress();
  String getName();
  void setName(String name);
  void setAddress(Address a);
}
interface Address {
  String getDoorNo();
  String getStreet();
  String getCity();
  String getZipcode();
  String setDoorNo();
  String setStreet();
  String setCity();
  String setZipcode();
}


Factory holds list of data binding POJO 

interface AppAutoBeanFactory extends AutoBeanFactory {
  // Factory method for a simple AutoBean
  AutoBean<Person> person();

  // Factory method for a non-simple type or to wrap an existing instance
  AutoBean<Person> person(Person toWrap);
}

Decode JSON to POJO



AppAutoBeanFactory factory = GWT.create(AppAutoBeanFactory.class);
AutoBean<Person> autoBean = AutoBeanCodex.decode(factory, Person.class, json);

Person personPojo = autoBean.as();


Encode POJO to JSON

AppAutoBeanFactory factory = GWT.create(AppAutoBeanFactory.class);
// Construct the AutoBean
AutoBean<Person> person = factory.person();
person.setName(...);
....
AutoBeanCodex.encode(person).getPayload();





Wednesday, May 15, 2013

Performance Tuning On GWT Applications


Performance Tuning On GWT Applications

                            This article discuss about various aspects of tuning your app. I have placed few information from experience and read from an internet.

Common Causes of Performance Issues


                Following site impressed so much, which not restricted to GWT good guidelines for all web app.


Java Collections API to handle a large amount of data.

The Collections API on GWT is very slow when compared with native javascript arrays and maps. Even when you use java arrays, they are much slower than native javascript ones.

You can read more detail comparison report here.

To solve it, you can use Crux collection API. It uses the java Collections when running on Dev Mode and native arrays and maps for web mode.

or

GWT Lightweight Collections. Between other improvements they promised to bring minimum size of compiled script and absolute maximum speed. GWT Lightweight collections designed to be client-side only. If you will want to transfer those using RPC mechanism you will likely end in the exception.

In general to speed up your JavaScript is to use Arrays instead of Collections where it is possible both for transport and processing. Arrays are closer to its JavaScript analogues and GWT does not compile-in too much wrapping code for compatibility purposes.

RPC interfaces that declare very generic parameters

When you are designing interfaces to access the server side of application using GWT RPC, you must care with your parameters and exceptions types.

To implement your method calls, GWT needs to serialize the objects passed as parameters (and also return types, exceptions thrown, etc.). To do this, it creates TypeSerializers for those types.

Behind the scenes, you will have genereted javascript objects to represent your rpc classes. These objects will contain some maps. These maps contains entries pointing to the necessary TypeSerializers.

So if you declare something like:


1
2
3
4
5
6
7
8
9
10
11
package com.mycompany.client.remote;
 
import java.io.Serializable;
import java.util.List;
 
import com.google.gwt.user.client.rpc.RemoteService;
 
public interface MyRPCService extends RemoteService
{
 void myMethod(List< Serializable > parameter) throws Exception;
}

GWT will need to create serializers for all possible exceptions (all ones within your client folder), because your method can throw any exception. It will need to create serializers for all kind of Lists (ArrayList, LinkedList, etc) and for any class that implements Serializable.

It will generate a very big number of TypeSerializers and turn that javascript map of serializers, mentioned earlier, into a very big map, wasting memory and making your application slower.

You should declare your interfaces as much specific as possible, like on the example:


1
2
3
4
5
6
7
8
9
10
package com.mycompany.client.remote;
 
import java.util.ArrayList;
 
import com.google.gwt.user.client.rpc.RemoteService;
 
public interface MyRPCService extends RemoteService
{
 void myMethod(ArrayList< String > parameter) throws MyException;
}

Other important point is try to pass only the minimum required as parameters and return types. It will decrease the amount of data serialized and transmited through the network.

Excessive number of accesses to the page DOM


Especially in IE, access the DOM is very slow. Hence, we should try to code in order to reduce the number of accesses.

Whenever possible, use variables, as a form of cache to the DOM elements that are frequently accessed, avoiding run many calls to getElementById().

It is essential to monitor the behaviour of your application with a good profiler tool to identify how to reduce these accesses and manipulate the DOM in a proper way. We strongly suggest Dynatrace for it.

Even if you're not manipulating the DOM directly, you must be aware of this problem, since the way your code is written can change how the code generated by GWT accesses the DOM.

As an example, imagine a case where we need to create an HTMLPanel and add several widgets inside it, on specific positions. We can write this code like:
1
2
3
4
5
6
7
8
9
10
11
public void myMethod()
{
 HTMLPanel htmlPanel = new HTMLPanel(html);
  
 htmlPanel.add(new Button(), "myButton");
 htmlPanel.add(new TextBox(), "myTextBox");
 htmlPanel.add(new ListBox(), "myListBox");
 //other widgets ...
   
 RootPanel.get().add(htmlPanel);
}
And we can also write like:
1
2
3
4
5
6
7
8
9
10
public void myMethod()
{
 HTMLPanel htmlPanel = new HTMLPanel(html);
 RootPanel.get().add(htmlPanel);
  
 htmlPanel.add(new Button(), "myButton");
 htmlPanel.add(new TextBox(), "myTextBox");
 htmlPanel.add(new ListBox(), "myListBox");
 //other widgets ...
}


The two versions are very similar, but the performance is very different. The first version is much slower.

The reason for this is how the widget HTMLPanel works. The method add(Widget, String) adds the widget within the element with id entered as the second parameter of the method.

To find this element, the HTMLPanel runs the getElementById command. The point is that the HTMLPanel is not attached to the DOM yet, what would cause the method getElementById returns nothing. Thus, when the add method is called before the panel be attached to the DOM, it attaches itself to a temporary element in DOM, runs the getElementById method and then removes itself from the temporary element.

Thus, the first code shown generates much more changes in the DOM than the second (becoming slower), although the end result is the same.

You must also be careful when choosing the widgets to your page. To present a large amount of data, use the GWT new Cell widgets (in the place of the old Grids and Tables) that are much faster, because they build the widget HTML as a string before attach it, making much less accesses to DOM.

Build all widgets eagerly

A very common problem on applications is to build all widgets at the same time, when the page loads. It is a very bad practice that makes your application slow.

You must always render strictly what is necessary on each moment. Try to create your widgets lazily, when they become necessary.

Using GWT's LazyPanel you can make your application faster, by rendering some widgets only when they are needed. Widgets whose contents are conditionally visible (like DeckPanels and DisclosurePanels) can make an excellent usage of the feature provided by the lazy mechanism.

String handling is slow, particularly in Internet Explorer

               Even with the new StringBuffer class, you still need to be careful when dealing with strings. Some of the StringBuffer methods are implemented by calling toString() and doing something on the result. That can be a real performance killer. So anything you can do to stay away from substring()charAt(), etc. will help you. This can mean that it’s sometimes better to work with plain String instead of StringBuffer.

Lets see an example. We have some components that need to make a lot of string comparisons. These comparisons are made inside a very big loop.

When GWT compiles the code to javascript, it will produce the following code for the String.equals() method:

1
2
3
4
5
6
7
8
9
function java_lang_String_$equals__Ljava_lang_String_2Ljava_lang_Object_2Z(this$static,other)
{
 if(!(other != null &&
            com_google_gwt_lang_Cast_canCast__IIZ(other.java_lang_Object_typeId$, 1)))
 {
  return false;
 }
 return  String(this$static) == other;
}

Any javascript programmer would see this code and think: "To compare two strings I could just write one line of code and use the === operator!!!". Yes, it is wright, but GWT implements the method in order to make it compatible with the java API. The method equals() receives an Object as parameter, and it needs to handle any type differences. It checks if the parameter can be cast to String (if it is another String or a subclass of it.)

However, if we detected that the loop with comparations is creating a performance issue, we could use a trick. We could create a static method to do this comparation faster. See the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class StringUtils
{
  public static boolean unsafeEquals(String a, String b)
  {
   if (GWT.isScript())
   {
    return a==b;
   }
   else
   {
    return a.equals(b);
   }
  }
}

Then, we just change the loop to something like:


1
2
3
4
5
6
7
for (int i=0; i < veryBigIndex; i++)
 
 if (StringUtils.unsafeEquals(a, b))
 {
  // ...
 }
}

The result is that the equals method will be used on DevMode and the final javascript (for web mode) will be generated as:


1
2
3
4
5
6
7
for (var i=0; i < veryBigIndex; i++)
{
 if (a == b)
 {
  // ...
 }
}


We don´t need to care with type parameter differences because the unsafeEquals method signature declares its parameters as Strings, so the compiler will ensure the types compatibility, once String is a final class and can not be overridden.

Note that unsafeEquals is not checking for null parameters (that's why it is called "unsafe").

That example was extracted from a real case, where we obtain a considerable gain.

However, it is important to emphasize that we could not use this kind of trick indiscriminately. It would turn our code more complex to read and maintain  It must be used when we are faced with a performance issue, detected previously with a profiler tool.

Besides all the problems mentioned above, you need to remember that we are talking about web applications. The discussion on this post is focused on problems strictly related with GWT, but we also need to think on all aspects of the web application.
We need try to reduce the number of requests, use cache and expires headers properly, and follow all good practices related with this kind of development.

GWT has given few guidelines


Use profilers for analyzing size and performance

                  See my blog for "How to profile javascript using chrome.