slartidan
slartidan

Reputation: 21586

Storing complex GWT-Types as Javascript

In my first GWT module I want to store a JavaScript object, later on I want to receive this object in my second GWT module. Everything works fine for primitive types, but my complex type will always have all fields set to "undefined".

My class, that I want to transfer from one module to the other:

public class SomeThing {
    public Set<String> strings = new HashSet<String>();
}

The entry point of my first module looks like this:

public class EntryA implements EntryPoint {

    @Override
    public void onModuleLoad() {

        // define test data
        SomeThing someThing = new SomeThing();
        someThing.strings.add("hallo123");

        // save data to JavaScript
        saveToJavaScript(someThing);

        // read and show saved data
        Window.alert("ModuleA:"+readFromJavaScript());
        Window.alert("ModuleA strings:"+readFromJavaScript().strings);
    }

    private native void saveToJavaScript(SomeThing thing) /*-{
        $wnd.storedThing = thing;
    }-*/;

    private native SomeThing readFromJavaScript() /*-{
        return $wnd.storedThing;
    }-*/;

}

The entry point of my second module looks like this:

public class EntryB implements EntryPoint {

    @Override
    public void onModuleLoad() {

        // run delayed, so that ModuleA will be executed first
        new Timer() {

            @Override
            public void run() {

                // read and show saved data
                Window.alert("ModuleB:"+readFromJavaScript());
                Window.alert("ModuleB strings:"+readFromJavaScript().strings);
            }
        }.schedule(5000);
    }

    private native SomeThing readFromJavaScript() /*-{
        return $wnd.storedThing;
    }-*/;

}

I am compiling each module separately. Both generated JavaScript files are included in one html file.

The output is:

ModuleA:moduleA.client.SomeThing@a
ModuleA strings:[hallo123]
ModuleB:moduleA.client.SomeThing@a
ModuleB strings:undefined

Does anyone have an idea how to store such complex types? Let me know, if you need some more information.

UPDATE

I found out, that it actually works, if I am "refreshing" the fields in JavaScript. I have no idea why this works!

    private native SomeThing readFromJavaScript() /*-{

        var a = $wnd.storedThing;
        [email protected]::strings = a['moduleA_client_SomeThing_strings'];

        return $wnd.storedThing;
    }-*/;

Nevertheless I need a generic approach, which allows to transfer any object - and I don't want to have to mention every possible field... :(

Upvotes: 0

Views: 254

Answers (2)

BobV
BobV

Reputation: 4173

The reason that you can't read fields between GWT modules is that each module is compiled and obfuscated independently. This means that SomeThing.strings could be mapped to .a in one module and `.q' in another. Your "refresh" trick only works because compiling the module in detailed mode usually results in the same name.

You might want to consider using the AutoBeans framework, which supports JSON-encoding the objects in a stable manner.

Upvotes: 0

Peter Knego
Peter Knego

Reputation: 80340

Maybe this has something to do the way modules are loaded.

The preferred way to load multiple modules it is described in: Loading multiple modules in an HTML host page:

If you have multiple GWT modules in your application, there are two ways to 
approach loading them.

1. Compile each module separately and include each module with a separate 
<script> tag in your HTML host page.

2. Create a top level module XML definition that includes all the modules you 
want to include. Compile the top level module to create a single set of 
JavaScript output.

...[cut for brevity] The second approach is strongly recommended.

Upvotes: 1

Related Questions