views:

31

answers:

1

Traditionally we have always used xml in the response which is parsed by a Javascript method to execute post processes. I came up with a new, simpler implementation which uses a hidden input set by a requestAttribute and executed in an ajax callback.

JSP:

<%
    String jsPostProcess = (String)request.getAttribute("jsPostProcess");
    if (jsPostProcess!=null && jsPostProcess.trim().length()>0){        
%>
        <input type="hidden" id="jsPostProcess" name="jsPostProcess" 
            value="<%= jsPostProcess %> "/>
<%  } %>

AJAX CALLBACK:

var callback = {
    success: function(response) {
        var div = $(divId);
        if (div){
            div.innerHTML = response.responseText;              
        }
        var jsPostProcess = $('jsPostProcess');
        if (jsPostProcess)
            eval(jsPostProcess.value);
    },
    failure: function(response) {
        alert('Something went wrong!');
    }
}

SERVLET CODE:

request.setAttribute("jsPostProcess", jsPostProcess);

It works beautifully, and it is so much simpler for adding js post processes to virtually any call no matter how simple or complex the functionality is. No need for customized js methods for parsing.

Curious if anyone could identify any potential problems with it (such as security issues?) or make any suggestions for other alternatives. We currently use Prototype and YUI 2 on the front-end.

+1  A: 

First, there's no need for that unpleasant scriptlet code:

<c:if test='${not empty jsPostProcess}'>
  <input type='hidden' id='jsPostProcess' name='jsPostProcess' value='${jsPostProcess}'>
</c:if>

Next thing is that I hope that somewhere before this point the "jsPostProcess" value has been scrubbed so that it doesn't break the markup (like, in case it includes quotes).

Just calling eval() on the value like that seems a little dangerous, though perhaps you know pretty well what it's going to be.

Finally I would offer the suggestion that as an alternative to that, if the "post process" code isn't too big you could send it back in a response header. Then you wouldn't have to drop any meaningless markup into your page.

Oh, also finally: you might want to make the <input> be disabled. Or, alternatively, you don't even have to use an input: you can use this trick:

<script id='jsPostProcess' type='text/plain'>
  ${jsPostProcess}
</script>

Because the "type" attribute is "text/plain" the browsers won't try to execute that code, and you can get the "text" of the <script> element whenever you want.

Pointy
Thanks for the response!! Once I re-read your post a few times I got it all to work (despite my previous comment which I edited lol!!). Excellent suggestions. Much appreciated!
skel625
"Just calling eval() on the value like that seems a little dangerous, though perhaps you know pretty well what it's going to be." I thought the same thing, but I couldn't think of any way this could be used maliciously, since the post-processes are all pretty much standard events that do not allow any more "hack-ability" than is normally possible by the user. But I'm no expert on js security issues!! ;)
skel625
Well so long as that stuff doesn't have any user-supplied content in it, you're OK. If it does, then there are some ways to protect yourself there too.
Pointy