JBoss Seam 2.2.0 and Google Web Toolkit (GWT) 2.0.0 support

I should have published this sooner when my colleague (Radovan Sninský, working with me on Java Simon among other things) came with the solution how to call Seam components from GWT 2 (probably in milestone 1 already). GWT 2.0.0 changed some details in its RPC protocol and built-in Seam support for GWT stopped working with errors like this:

2010-02-09  10:28:12,265 ERROR  [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/whatever]]  (http-127.0.0.1-8080-1) An IncompatibleRemoteServiceException was  thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException:  Parameter 0 of is of an unknown type 'some.Class/some number'
at  org.jboss.seam.remoting.gwt.GWTService.RPC_decodeRequest(GWTService.java:426)
at  org.jboss.seam.remoting.gwt.GWTService.processCall(GWTService.java:203)
at  org.jboss.seam.remoting.gwt.GWTService$1.process(GWTService.java:120)
at  org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHttpServletRequest.java:53)
at  org.jboss.seam.remoting.gwt.GWTService.getResource(GWTService.java:105)
at  org.jboss.seam.servlet.SeamResourceServlet.service(SeamResourceServlet.java:80)
...
Caused  by: java.lang.ClassNotFoundException: some.Class/number
at  java.lang.Class.forName0(Native Method)
at  java.lang.Class.forName(Class.java:247)
at  org.jboss.seam.remoting.gwt.GWTService.RPC_getClassFromSerializedName(GWTService.java:479)
at  org.jboss.seam.remoting.gwt.GWTService.RPC_decodeRequest(GWTService.java:422)
... 46 more

As GWT 2.0 is fresh it was obviously better to patch Seam. And because GWT calls are processed using awesome Seam Adapters (I really like this concept!) we decided to duplicate the existing Adapter and just rewriting problematic parts. The RPC protocol changes were very subtle but it was big enough to blow out in case of Long types and probably some others too. Radovan then copied a few classes from Seam and added some of his code, fixed some lines and registered his GWT Service adapter on the URL suffix /gwt2. That way the only thing you need to do in your project is:

  • download this ZIP
  • unzip it into your src directory and let it be compiled along with EJB part of your application – if you move classes to another package, fix package declaration as well in all 5 classes
  • change the method in GWT UI part where you retrieve the service point – for example:
SomeServiceAsync svc = GWT.create(SomeService.class);
((ServiceDefTarget) svc).setServiceEntryPoint(GWT.getHostPageBaseURL() + "seam/resource/gwt2");

The important part is “gwt2” at the end instead of “gwt”. If you have your URL in some constant, change it there. Recompile, rebuild, redeploy, restart, try it – it should work now. Of course – if you’re really using GWT 2.0.0. 🙂

Licensing? Well… I guess it is LGPL like the original Seam sources. Hopefully there is no Seam 2.3 with GWT 2 support around the corner (doesn’t seem so) which would render this post useless in a day. 😉

Advertisements

Salix GWT Tree

Talking about DIY may be sign of a man that can handle some things and doesn’t rely on other’s work. Reinventing the wheel – on the other hand – means someone is stupid enough to do what is already done. Of course it is easy to reinvent that wheel when you don’t know it has been invented already. When you don’t know how to check it out, or when you checked it out but the search didn’t provide proper answer (that may – again – mean that one is stupid to search properly :-)). Whatever you can say about writing “new, simple, custom” whatever – when it does solve the problem in reasonable time frame, it’s sometimes the best thing to do. Even if it’s the wheel. Or the tree.

In this case I’m talking about my recent GWT Tree troubles. I assigned my workmate with some task based on the idea of a tree as good/nice as GWT-Ext one without using any other library, he came up with solution, we’re now cleaning it up and adding things we like and need (automatic sorting, connectors, custom icons for connectors, …) – but the important thing is – we have the Tree we can use! We call the project Salix (yeah, there is some Salix OS too, it’s really difficult to come up with some brand new tree name after we decided to move from something as original as “Simple Tree”) and you can find it on it’s Google Code project page.

I took care of the initial page and while the code is far behind Java Simon standards (other project I participate on) I’m sure you can find everything necessary right away on the first page. If you like the idea, if you struggle with GWT default tree, try it, send us feedback, patch, idea, code, whatever. We don’t plan to work on this project just for the sake of the project itself. We fulfilled our needs and published the result – nothing more, nothing less. Maybe you will like this… ehm… simple Tree too. 🙂

Google Chrome with perspective

I can hardly believe that it’s almost a year I started to use Google Chrome browser! While I still use it at home I decided to switch back to Firefox at work – for a simple reason. Chrome is very stubborn when accessing https sites without proper certificate. We have a few on our corporate intranet and while I can simply accept any certificate forever with Firefox, it’s not so easy with Chrome. I’ve found some blog posts how to import certificate permanently in Windows, but somehow I failed to do so (maybe I messed up, maybe something else is wrong). I like to tweak things, but sometimes I’m just lazy to fix things that should be easy. That are easy somewhere else with something else. Like Firefox in this case.

I still use Google Chrome at home though, but I’m closer and closer to abandon it there as well. Do you use Google Docs? I do. When I open the document (I write now), I click on its title, little dialog box appears with the label “Enter new document name:” and the input box with the title of the document. It seems to be selected, so CTRL+C, go somewhere else, CTRL+V and guess what appears: “Enter new document name:” Hm, strange… I go there again, I select few characters from the title, copy/paste… again, the same result. I found out when I wanted to copy title to the WordPress. But I clearly remember it to work! But yeh, wait… in which browser? In Firefox it works like a charm. Well not a charm actually, it simply works like it SHOULD in the first place.

Last problem I have with Google Chrome is more technical and is related to Google Web Toolkit we started to use. Biggest trouble here is that I probably have to tackle this one but so far I’m stuck without any idea. If you’re not a programmer, stop reading and consider the article finished. If you are…

GWT compiles Java code to JavaScript which means you can write an application in Java (Google’s special libs) and then run it in the browser as a nice rich application with AJAX support and much more. You can load the resulting JavaScript on the HTML page and it works somehow. Now I wanted to generate HTML page with JSF/Facelets and power the server-side with JBoss Seam. Resulting HTML page is exactly the same, HTTP response headers are a bit different, but nothing serious. The application works fine in Firefox, IE, anything… except Google Chrome where it throws funny exception:

Uncaught TypeError: Object #<a Document> has no method 'write'

The script with the problem is generated and this particular part is some service stuff – not the result of my Java code. Problem is on the third line here:

function computeScriptBase(){
var thisScript, markerId = $intern_8, markerScript;
$doc.write($intern_9 + markerId + $intern_10);

Now how can anyone starting with GWT probably resolve this? Honestly I have no idea what is happening there and why it works fine in anything but Google Chrome. Now I hosted the SAME script in plain HTML, I ran telnet to my application server and this is how it looks (uff, now I had a problem to copy/paste this as well as it removed all my new lines from a plain text – in Chrome, so I’m now finishing it in Firefox :-)):

$ telnet xxx 8080
Trying xxx...
Connected to xxx.
Escape character is '^]'.
GET /comasutra/main.seam?cms HTTP/1.1
Host: xxx:8080

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Set-Cookie: JSESSIONID=8727F8532EA49A8FAB7E967245D5F27C; Path=/comasutra
X-Powered-By: JSF/1.2
Content-Type: text/html;charset=UTF-8
Content-Length: 823
Date: Wed, 05 Aug 2009 13:39:07 GMT

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="gwt:property" content="locale=sk" />
<title>Comasutra</title>
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
<script type="text/javascript" language="javascript" src="cms/cms.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex="-1" style="position:absolute;width:0;height:0;border:0"></iframe>
<div class="top">
</div>
<div class="main">
<h1>Main page</h1>
<div>
<h2>Articles</h2>
<div id="cms-c1" class="article-list"></div>
</div>
</div>
</body>
</html>

GET /comasutra/bubu.html?cms HTTP/1.1
Host: xxx:8080

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Set-Cookie: JSESSIONID=650F5FDDED9EC66D0C810B6C2D69B1CC; Path=/comasutra
Accept-Ranges: bytes
ETag: W/"823-1249478709000"
Last-Modified: Wed, 05 Aug 2009 13:25:09 GMT
Content-Type: text/html
Content-Length: 823
Date: Wed, 05 Aug 2009 13:48:29 GMT

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="gwt:property" content="locale=en" />
<title>Comasutra</title>
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
<script type="text/javascript" language="javascript" src="cms/cms.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex="-1" style="position:absolute;width:0;height:0;border:0"></iframe>
<div class="top">
</div>
<div class="main">
<h1>Main page</h1>
<div>
<h2>Articles</h2>
<div id="cms-c1" class="article-list"></div>
</div>
</div>
</body>
</html>
Connection to xxx closed by foreign host.

Just to be complete: We use JBoss Seam 2.2.0.CR1, JBoss AS 5.1.0.GA, GWT 1.7, Windows XP SP 3, Google Chrome 2.0.172.39.

Obviously, the first GET request is JSF/Seam one, the other one uses plain HTML. HTMLs are exactly the same, headers are different. I don’t know if subsequent request for “cms/cms.nocache.js” is different, but the whole thing blows out in the JS execution after all. I really don’t know where is the problem. And I’m quite sick to even have a problem like this. Maybe it’s not the Chrome only, maybe it’s the JS engine. Will I have the same trouble with Safari on Mac? I don’t know because I can’t try it any time soon. But in the end there are more little usability problems with Chrome than I expected. I’ll probably give it a try again after some update, but for now I’m switching my default browser back to Firefox. And I’ll probably have to add a note that “this application is not supported in Google Chrome”. I’d be ashamed, but I’m rather pissed off really.