How to access data across modules in GWT? - gwt

I have two GWT modules with its own entry point, ModuleA and ModuleB. I am using Window.assign() to move from ModuleA to ModuleB. One Variable value is set in ModuleA. How to access the same value from ModuleB?
Thanks in advance.

I have written a couple of answers which could help you to deal with this.
Since you cannot share pure java between two compiled modules: GWT: How to share a java Object (ie: EventBus) between two modules, I suggest to export methods using jsni: How to communicate two modules in GWT. But I would use gwt-exporter or gwt-query to avoid writing js by hand which normally is a source of mistakes: Calling GWT Java function from JavaScript
Note, that these solutions only work in the case both modules are loaded in the same html.
If you want to pass a value to a different page downloading the actual, you can append those values to the new url and read it in the second application:
// Module A
Window.Location.assign("module_B.html?msg=whatever");
// Module B
String msg = Window.Location.getParameter("msg");

IMO the best way would be to implement the observer/observable pattern in pure JavaScript in your host page, and use JSNI in your application to register handlers/fire events.

Related

ELKI: Implementing a custom ResultHandler

I need to implement a custom ResultHandler but I am confused about how to actually integrate my custom class into the software package.
I have read this: http://elki.dbs.ifi.lmu.de/wiki/HowTo/InvokingELKIFromJava but my question is how are you meant to implement a custom result handler such that it shows up in the GUI?
The only way I can think of doing it is by extracting the elki.jar package and manually inserting my custom class into the source code, and then re-jarring the package. However I am fairly sure this is not the way it is meant to be done.
Also, in my resulthandler I need to output all the rows to a single text file with the cluster that each row belongs to displayed. How tips on how I can achieve this?
There are two questions in here.
in order to make your class instantiable by the UIs (both MiniGUI and command line), the classes must implement our Parameterization API. There are essentially two choices to make your class instantiable:
Add a public constructor without parameters (the UI won't know how to set your parameters!)
Add an inner static class Parameterizer that handles parameterization
in order to add your class to autocompletion (dropdown menu), the classes must be discovered by the MiniGUI/CLI/other UIs. ELKI uses two methods of discovery:
for .jar files, it reads the META-INF/elki/interfacename service files. This is a classic service-loader approach; except that we also allow ordering instances.
for directories only, ELKI will also scan for all .class files, and inspect them. This is mostly meant for development time, to avoid having to update the service files all the time. For performance reasons, we do not inspect the contents of .jar files; these are expected to use service files.
You do not need your class to be in the dropdown menu - you can always type the full class name. If this does not work, adding the name to the service file will not help either, but ELKI can either not find the class at all, or cannot instantiate it.
There is also a tutorial on implementing a custom result handler, but it does not discuss how to add it to the menu. In "development mode" - when having a folder with .class files - it will show up automatically.

Compiling/Joining CoffeeScript files in correct order

Correct me if I am wrong, but it appears that CoffeeScript does not compile/join code (each class has its own file) in the correct order.
If I have these classes in the following files:
Button.coffee
class Button extends UIComponent
UIComponent.coffee
class UIComponpent
When I compile these classes (using the --join flag), it outputs the classes in the incorrect order (i.e. putting Button ahead of UIComponent). So when the referenced .js file is used on a web page, it throws the "Cannot read property 'prototype' of undefined" error
Is this an issue that anyone else experiences? If so, is the standard use of CoffeeScript to not use classes? I'm just confused on why this doesn't appear to be a standard implementation? Perhaps I am using CoffeeScript incorrectly.
CoffeeScript isn't responsible for your dependency management.
You could use something like require.js to define your dependencies, then use CoffeeScript to compile your JavaScript files separately, and then use the r.js optimiser to minify and concatenate your compiled JS.

GWT Client Server Communication

I'm wondering whether it is at all possible to make the client ask the server for a given string, and incorporate it into another string ?
I don't see how to do that using the async approach.
As far as I know there is no really simple way to do this, because the i18n machanism of GWT replaces strings at compile-time and not at runtime.
You can try one of the following approaches:
Load the i18n in your entrypoint, store all messages in a local Map and create the Label etc, with the values from you cache. PRO: all GWT standard CONS: one request more, before you can show a translated page
Use JSP and no HTML at serverside. Wthin you jsp can create a JSON from your
message.properties and put it into your hostpage. PRO: You can synchronous read te values CONS: You will need to write a JSP which reads the properties for the correnct language, You will need to write a JSNI method to load the translated values.
Rethink, if you need a different way of translation. The built-in i18n will create tranlated versions of your app at compile-tim
I think I would use the second approach.

Where to add i18n files in a project (for my case GWT)?

I can't find a good answer to this simple question:
Where can I add my i18n files in a GWT project ?
I see two solutions:
- create a module and add all i18n files for this module in this module
- create a complete different structure to put all i18n files (no matter what module) in the same directory (and so, easy to create a new language)
My feeling is that the second approach is better but in gwt samples, it's the first approach which is generally used.
And you, what do you do with yours i18n files ?
Thanks
1) Create a separate package in your module. Dump all message files there along with the property files.
2) As a best practice create a base message class and EXTEND other message interfaces from the base one. You can reference base message class in code and depending on which instance of message class you point too, your actual value will change.
Another approach, create a new i18n module and inherit that in your actual model.
1) Allows all messages to be in one place.
2) Easy to hand over to localization people for translation.
I usually put the i18n files (*.properties) in the same package as the Constants (or any other i18n related class) derived interface that's using them (less hassle with setup) - usually the package is named i18n.

gwt lazy loading

Is it possible in a large GWT project, load some portion of JavaScript lazy, on the fly?
Like overlays.
PS: Iframes is not a solution.
Check out GWT.runAsync as well as the Google I/O talk below, which goes into lazy loading of JavaScript in GWT projects.
http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting
http://code.google.com/events/io/sessions/GoogleWavePoweredByGWT.html (around time 25:30)
I think this is what you are looking for.
<body onload="onloadHandler();">
<script type="text/javascript">
function onloadHandler() {
if (document.createElement && document.getElementsByTagName) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = './test.js';
var heads = document.getElementsByTagName('head');
if (heads && heads[0]) {
heads[0].appendChild(script);
}
}
}
function iAmReady(theName) {
if ('undefined' != typeof window[theName]) {
window[theName]();
}
}
function test() {
// stuff to do when test.js loads
}
</script>
-- test.js
iAmReady('test');
Tested and working in Firefox 2, Safari 3.1.2 for Windows, IE 6 and Opera 9.52. I assume up-level versions of those should work as well.
Note that the loading is asynchronous. If you attempt to use a function or variable in the loaded file immediately after calling appendChild() it will most likely fail, that is why I have included a call-back in the loaded script file that forces an initialization function to run when the script is done loading.
You could also just call an internal function at the bottom of the loaded script to do something once it has loaded.
GWT doesn't readily support this since all Java code that is (or rather may be) required for the module that you load is compiled into a single JavaScript file. This single JavaScript file can be large but for non-trivial modules it is smaller than the equivalent hand written JavaScript.
Do you have a scenario where the single generated JavaScript file is too large?
You could conceivably split your application up into multiple GWT modules but you need to remember that this will limit your ability to share code between modules. So if one module has classes that reference the same class that another module references, the code for the common class will get included twice.
Effectively the modules create their own namespace, similar what you get in Java if you load the same class via two separate class loaders. In fact because the GWT compiler only compiles in the methods that are referenced in your code (i.e it does dead code elimination), it is conceivable that one module will include a different subset of methods from the common class to the other module.
So you have to weigh up whether loading it all as one monolithic module and taking an upfront hit the first time round is better than having multiple modules whose cumulative code size might well be significantly greater than the single module approach.
Given that GWT is designed so that the user should only ever load the same version of a module once (it is cached thereafter), in most cases the one off upfront hit is preferable.
Try to load a big GWT application with the "one upfront" approach using a iPhone or an iPod touch...it will never load.
The module approach is a but more complexe to manage but better for smaller client devices.
Now, how do I load a module from my Java code without using an iFrame?
Erick