26 July, 2007

Portals and Portlets with GWT modules

Last week I considered possibility of using portlets and GWT modules together (i.e.: GWT inside portlet's window).
And I'm coming to conclusion that it works. And it works pretty good.

I created several portlets with GWT modules, and also I wrapped some of my GWT applications in a portlets.

One of them - ChatPortal (simple application for messaging).

First edition of ChatPortal worked well. But I couldn't put several instances of ChatPortlet windows into the page and couldn't move portlet's window within the page.

I investigated these problems and found solution how to resolve theirs.

I changed some ChatPortal's code and Second edition works excellent!

Now I'm using a "-xs" ("cross-site") version of my module's, which GWT (v1.4) compiler produces.
I.e.: instead of gwt.js or xqx.web.chat.Chat.nocache.js scripts I use xqx.web.chat.Chat-xs.nocache.js.

And also I found way how to have several windows instances for one portlet within one page. I wrote function, which performs tree-walking over the HTML DOM and finds places where to put my widgets.

See sources below, they'll say more.

Dashboard with several instances of portlets with same GWT modules



Moving of portlet with GWT module





ChatPortlet.java
public class ChatPortlet extends GenericPortlet {

AtomicInteger counter=new AtomicInteger(0);

protected void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException {
renderResponse.setContentType("text/html");
PrintWriter writer = renderResponse.getWriter();
writer.println("<script language='javascript' src='" + renderRequest.getContextPath() + "/xqx.web.chat.Chat-xs.nocache.js'></script>");
writer.println("<div id='xqx_web_chat_Chat-"+counter.incrementAndGet()+"'></div>");

writer.close();
}

...
}


Chat.java
package xqx.web.chat.client;
...
public class Chat implements EntryPoint {
...
private FlowPanel messagesPanel = new FlowPanel();
private ScrollPanel messagesScrollPanel = new ScrollPanel(messagesPanel);

private TextArea inputTextArea = new TextArea();
private ScrollPanel inputScrollPanel = new ScrollPanel(inputTextArea);
...
public void onModuleLoad() {

messagesScrollPanel.setStyleName("xqx_messagesScrollPane");
messagesScrollPanel.addStyleName("xqx_etchedBorder");

inputTextArea.setStyleName("xqx_input");
...

String slotId = getEmptySlotId(RootPanel.getBodyElement(), "xqx_web_chat_Chat");
RootPanel rootPanel = RootPanel.get(slotId);

if (rootPanel != null) {
...
rootPanel.add(messagesScrollPanel);
rootPanel.add(inputScrollPanel);
rootPanel.add(sendButton);
...
}

...
}

private String getEmptySlotId(Element element, String idPrefix) {
int count = DOM.getChildCount(element);
if (count == 0) {
String id = DOM.getElementAttribute(element, "id");
if (id != null && id.startsWith(idPrefix)) {
return id;
}
} else {
for (int i = 0; i < count; i++) {
String id = getEmptySlotId(DOM.getChild(element, i), idPrefix);
if (id != null)
return id;
}
}
return null;
}

private void printMessages(Message[] messages) {
...
}
}



I use GWT v1.4 beta and JBoss Portal 2.6.



You may download these sources from Xantorohara.blogspot.com samples

5 comments:

Thomas Heute said...

Very Cool :)
Is the Chat portlet only for example or are you working on a production ready version ?

Xantorohara said...

Currently it is only example, because
I don't have any customers for this.

AH said...

Very cool. Is there anyway to obtain the user id from JBoss Portal so that you can log the user in automatically into the chat?

Xantorohara said...

I'll look at it under debugger and will write.

Unknown said...

How do you instruct the file to generate the -xs.nocache.js file? I am using the ant file you included in your other GWT portlet example blog. Also, does this solve the problem with the screen going blank when you add the portlet to the portal? You approach to walking through the DOM is interesting. I have not worked on this much as I need it to act correctly before worrying about this, but I tried to pass the portlet namespace into GWT using the Dictionary module, but was unsuccessful. I will continue down this path for a bit and will let you know if I find a more efficient and flexable way of doing this.