16 July, 2007

GWT. Multiple widget's instances.

Portlets and GWT look nice together. At first sight.
There is one problem in their cooperation: we can't use multiple instances of same GWT modules in one html page, so we can't build normal portlet.

For example, I have simple GWT module with this entry point:

public class XLam implements EntryPoint {
...
public void onModuleLoad()
{
RootPanel.get("unique_html_element_id").add(somewidget);
}
}


And I would like to add this GWT module into my portlet. For this case I write code:

public class XLamPortlet extends GenericPortlet
{
protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, PortletSecurityException, IOException
{
...
writer.println("<script language='javascript' src='" + renderRequest.getContextPath() + "/xqx.web.xlam.XLam.nocache.js'></script>");
writer.println("<div id='unique_html_element_id'></div>");
...
}
}


When I try to place two same portlets into one page I get collision between GWT instances, of course.

I think, that should be way to resolve this problem and I'm trying to find it.

Has someone any solution for this?

Today I've researched JavaScript, which generated by GWT compiler.
I found some ways how to resolve this problem.

It is possible to change some parts of the *.js compiled code, e.g.:.

Rewrite in *.cache.html
..
function wq(a)
{
hh(pi('unique_html_element_id'), a.b);
hh(pi($wnd.unique_html_element_id), a.b);
a.c = lq(new kq(), a);
id(a.c, 1000);
}
...
Define variables 'on the fly' in *.nocache.js
...
var unique_html_element_id='unique_html_element_id';
...

Or, maybe, rewrite or append additional parameters to some functions like this:

function gwtOnLoad(b, d, c)

But all these are dead-end ways :-(


I think, Google may create useful mechanism for this.

How? I mean, via special parameter in EntryPoint.onModuleLoad() function.


GWT Team, it is really necessary for many web developers!

4 comments:

prasadgc said...

Hi,

I think the answer may lie with using Spring Portlet MVC.

The portlet classes should be defined with a local variable (say 'id'). Each instance of the portlet class used on a page would be configured in the Spring configuration file with a different value for the 'id' property field. This value can then be passed to the view JSP so that a different id is generated for the div tag.

I'm still trying to learn Spring Portlet MVC, so I can't tell you with confidence that this will work, but it's a promising area to research.

Xantorohara said...

I think, Spring Portlet MVC can't help in this situation, because it is not a problem to generate different Ids for several portlet's instances.

Problem in GWT, where Id hardcoded in generated JavaScript.

Unknown said...

Hi Guys, have a crazy solution: you can create servlet filter that will process all js files on the fly and replace some predefined const id(ex _000_code) with one specified in request parameter:
your jsp file will look like this:
--
script language='javascript' src='" + renderRequest.getContextPath() + "/xqx.web.xlam.XLam.nocache.js?id"+someJspParameterId+"
--
using this approach you will use same id in both jsp and gwt. Moreover, you can receive portlet id using portal specific API,
you just need to write that filter one time and reuse it. quite simple.
Regards,
Alexey
alex_vl_m@yahoo.com

rodrigob said...

What I do in this kind of circumstances, I write a GWT onModuleLoad that will parse the DOM searching for the desired elements (which can have varying number and type of instance) and them I generate (instanciate) and insert them on the needed places.

On GWT script per webpage, but the GWT script inserts as many widgets as the webpage needs...