Wednesday 20 June 2007

GWT and JSP 2.0 (Oh the Pain!)

So it's been four weeks now and I'm moving along at a steady pace with GWT.
I found by shear accident that a new feature added into GWT 1.4 is that you don't need the gwt.js anymore or the <meta..> tag in the HTML and you can just include the module.nocache.js file directly. (good change guys).

I have been trying to host my modules (GWT modules) into an already existing JSP page that is written in JSP 2.0 of the XML variety. I find these good because it means you are forced to create valid HTML markup. Anyways, combining the two, GWT and XML JSPs meant I was completely unable to get the GWT modules to attach and appear on the page.

I was getting JavaScript Errors, j.write is not a function. Now, the GWT compiler is compiling by default using the OBFuscation setting. Which means that the JavaScript, is well, obfuscated, a little hard to read. Not knowing yet what the other settings are to change it (I think there is detailed and something else I saw) I dove (breifly) into the JS to see what j.write was all about.

It took a bit to track down the problem.

Essentially weird things happen to your markup, it gets all compressed to one line (obfuscated HTML) and open, no content, close tag elements get changed to /> elements to make it more valid XML. For those that have worked with JSP XML documents (ie, the <jsp:root> ...</jsp:root> variety) will know what I am talking about.

The problem is that a jsp marked up this way just fails straight away with GWT in the works. I recalled a similar problem I had two years ago that was making javascript fail because the <script> tags written in the jsp as open <script> and closing </script> with no content in the middle (ie, a <script src="somefile.js"></script>) will get collapsed in the browsers view of the HTML as <script .. />. ie, just one tag.



To get around this JS error, back then, was to add a CDATA and put a comment delimeter in the CDATA. This way the JSP XML parser would preserve the open and close tags.

This looked like the following ..


<script src="somfile.js"><![CDATA[<!-- -->]]></script>


Which will bre rendered correctly as

<script src="somfile.js"><!-- --></script>

And the problem, can't remember what it was, but javascript loading issues, would work.

Alas, this was not my problem with GWT as I changed the <script ...></script> and the <iframe.../> to have this CDATA hack and it didn't resolve my j.write is not a function error.

So .. the quick simple test, cut and past the output of the JSP that has the GWT <script></script> in it, and put that as an HTML file and try that. So, refresh my broken page, view source, cut and paste the ugly format (hard to read for others) HTML and put it into a new .html file and load that, it worked.

So I have two files, tester.jsp which has the <jsp:root> top and bottom and then a html file which is the "output" viewed from the browser of this jsp file. So as far as the browser is concerned, hitting the /tester.jsp and /tester.html renders exactly the same looking HTML.

Which lead me to only one conclusion, it was not "format" of the HTML presented that the browser was barfing on, (and then GWT not loading) but rather the Headers that the server was sending that caused the problem.

Loading up firebug (just clicking my little firebug icon in firefox.. thank you thank you firebug authors), I inspected the headers of the tester.jsp and tester.html, low (lo) and behold,

tester.jsp : Content-Type: text/xml;charset=UTF-8
tester.html: Content-type: text/html

This then leads to the quick fix, change the content type for my JSP.

<jsp:root version="2.0" jsp="http://java.sun.com/JSP/Page">
<jsp:directive.page contenttype="text/html; charset=UTF-8"/>

And then all is good.

So, what is happening here ? It would appear that the browser (Firefox 2.0 on Mac OSX in this instance) is not creating a DOM that the GWT javascript can interact with when the content type is XML as opposed to when the content type is HTML.

This is evidenced by the line in question in the GWT module.nocache.js which is

j=document;

And a few lines in,

j.write("<script>...</script>")

From this called attempt to write out some dynamic javascript to the page, the specific error message obtained is as follows

j.write is not a function

Which just shows that the DOM is not how it is supposed to look. I am sure someone from the firefox community could explain that one a little more. (to how it structures the DOM based on content-type).

So this one was not because of GWT pain, but JSP pain :-)

All good so far. I have a few more improvements to the m2 GWT plugin which I will post in the next few days.

No comments:

Current 5 booksmarks @ del.icio.us/pefdus