Why two GWT applications cannot share the same JavaScript environment?

By | 13. Februar 2012

If you likes GWT as I do then you probably use it often and probably faced the same problem as I did.

The idea

The main advantage of GWT is that is makes dead simple to build very complex UI applications. That means I have to discipline myself to design the GWT application not as a monolithic monster with an initial download size of 2MB or worse (like happened to me in my first GWT project) – but as a lightweight, modular application that fetches only the needed code.

To avoid too large applications I’ve got a brilliant idea: I split the GWT app in different modules/widgets and include them wherever they are needed. In this way I could develop the modules independently from each other and they could communicate through a globally available EventBus.

The main advantage of this idea, as I thought, is that the modules does not have to know each other. And they are not depending on each other.

<html>
  <body>
    <div id="products"></div>
    <div id="basket"></div>
 
    <script type="text/javascript" src="products/products.nocache.js"></script>
    <script type="text/javascript" src="basket/basket.nocache.js"></script>
  </body>
</html>

I tried to implement that and I failed! And I’m happy about that because it’s a bad idea. So a had to start to think about the reason and to find a better way how I could achieve the same result.

Why it’s a bad idea?

Let’s assume we have a in the first GWT application a simple Product class with a sku and a price.

And in the second application we have a class named Basket with a sum and list of sku's.

// First GWT application
class Product {
  private String sku;
  private BigDecimal price;
}
 
// Second GWT application
class Basket {
  private ArrayList<String> skus;
  private BigDecimal sum;
}

The GWT compiler strips down the entire dependency tree and translates each referenced class into a javascript compilation. If those two classes would reside in two independent GWT modules, the String and BigDecimal classes would be compiled twice and would also be loaded twice into the javascript environment.

What is the problem?

If both modules compiled not obfuscated and loaded by the browser, then the String and BigDecimal implementations of the second module would overwrite the String and BigDecimal implementations of the first module. It means the same code is loaded twice.

As a common GWT application is a bit more complex than this example, you could imagine how easy it is to load with this idea the entire JRE stack multiple times. But that’s not the problem! The download size of the application increases, but it will work. The problem is the obfuscated code that we actually want to have because of it’s size.

Simply told, an obfuscater renames our classes into a shorter form. In the first module the Product class depends on the String and BigDecimal classes. String and BigDecimal have no dependencies (kept it simple for this example).

The obfuscater could start and rename the classes in their dependency order:

  1. java.lang.String becames a_A
  2. java.math.BigDecimal becames a_B
  3. de.fivews.Product becames a_C

In the obfuscated code a new Product would be created by executing new a_C()

Ok, lets have a look at the second module. The same thing here, but with one difference:

  1. java.lang.String becames a_A
  2. java.util.ArrayList becames a_B
  3. java.math.BigDecimal becames a_C
  4. de.fivews.Basket becames a_D

As you can see is everything fine if you load the first module. But when the second module is loaded the ArrayList class from the second module will overwrite the BigDecimal class from the first module. Just because of the renamed classes.

Now, what happens if the first module does this: new BigDecimal("2.3")?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.