Be careful feeding the ResponseWriter, use big bites

1 minute read

Earlier this week I got bitten by one of the consequences of writing JavaScript code in a Java environment. There are some things you need to be aware of and I for one was not.

In this case: the XPages run-time can’t always determine what the type is of the JavaScript value you’re feeding to a Java method. It can be problematic with single position values, either a string or a number. Is it a char, a String or an int?

What’s happening? Consider the following XPage:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var writer = facesContext.getResponseWriter();

writer.write("abc");
writer.write("a"); /* BOOM!! */

writer.endDocument();
}]]></xp:this.afterRenderResponse>
</xp:view>

You would expect this XPage to output abca, but it doesn’t. It will output abc and at the same time show the following error on the Domino server’s console:

HTTP JVM: com.ibm.xsp.exception.EvaluationExceptionEx: Error while executing JavaScript action expression

Changing the a to something with two characters fixed the error and gave the expected output. But feeding it the number 0 (which was my original problem) did not. 12 on the other hand was fine.

If course, this had to be a bug, so I send a nice little report to Paul Hannan. Unfortunately it’s not (so much for street credibility points), and Martin Donnelly explains why:

The com.sun.faces.renderkit.html_basic.HtmlResponseWriter class has overloaded write() methods - like this:

void write(char)
void write(char[], int, int)
void write(int)
void write(String)
void write(String, int, int)

For writer.write("g"); the engine does not know whether to call void write(char) or void write(String) on the Java side.

This is a general JavaScript to Java issue, as there is no JavaScript character type so we cannot be type-explicit on the SSJS calling side.

To pass in a single character to the writer class that you either: a) find a non-ambiguous version of a write method and force that to be called, b) declare the var as an explicit Java type and pass that in

Both are shown here:

var writer = facesContext.getResponseWriter();
writer.write(“abc”);
writer.write(“gh”);
//writer.write(“g”); //nope
// This will work …
writer.write(“z”,0,1);
// So will this …
var r = new java.lang.Character(‘r’);
writer.write(r);
writer.endDocument();

This problem can happen easily when you’re creating an XAgent. Be careful what you feed the writer.write(). If you’re not, you might get some hard to debug errors.

Happy hacking!

Categories:

Updated: