Struts Tip #10 - Use Struts JSP Tags to create dynamic JavaScripts

Ted Husted



The Struts framework ensures that we can perform data validation without the benefit if JavaScript. But that doesn't mean we can't use JavaScript in our Struts applications. Most web developers rely on JavaScript to provided core features on the presentation layer, and Struts developers are no exception.

Most JavaScript can be used on a Struts JSP like any other. After all, in the end, it all comes down to HTML.

Because it all comes down to HTML, you can mix JSP tags in with references to your JavaScript. The JSP code renders first, so by the time the browser sees it, any dynamic references have been resolved, and it just looks just like a static reference. Let's look at a script to open a remote window to preview a record from a database.

First a basic remote window script, just like you would use on a static page.

// Open window 
function HC_openWin(newURL, newName, newFeatures, orgName) { 
    var newWin = open(newURL, newName, newFeatures); 
    if (newWin.opener == null) newWin.opener = window; 
    newWin.opener.name = orgName; 
    return newWin 

// Open centered remote 
function HC_doOpenRemote(aURL, newName, aHEIGHT, aWIDTH, aFeatures, orgName){ 
    if (aHEIGHT == "*"){ aHEIGHT = (screen.availHeight - 80) }; 
    if (aWIDTH == "*"){ aWIDTH = (screen.availWidth - 30) }; 
    var newFeatures = "height=" + aHEIGHT + ",innerHeight=" + aHEIGHT; 
    newFeatures += ",width=" + aWIDTH + ",innerWidth=" + aWIDTH; 
    if (window.screen){ var ah = (screen.availHeight - 30); 
    var aw = (screen.availWidth - 10); 
    var xc = (( aw - aWIDTH ) / 2); 
    var yc = (( ah - aHEIGHT ) / 2); 
    newFeatures += ",left=" + xc + ",screenX=" + xc; 
    newFeatures += ",top=" + yc + ",screenY=" + yc;
    newFeatures += "," + aFeatures }; 
    var newWin = HC_openWin(aURL, newName, newFeatures, orgName); newWin.focus();
    return newWin 

We'll take this script as a given, since it is not the point of the exercise, and move on to how it is called from the JavaServer Page.

We want to use this script to open different database records at different times. To do this, we need to feed it a different URI to indicate which database record to open this time. In many applications, the URI would look something like


The "/do/item/View" part is relatively static. It just needs to be rewritten to maintain the session, but we saw how to do that in Tip #9. We can store it as an ActionForward and use the html:rewrite tag to render it at runtime.


    <forward name="item" path="/do/item/View"/>


    <html:rewrite forward="itemScript"/>

The dicey part is the ?item=117. This is the truly dynamic portion of the URI, and the part that we actively need to pass to the script. That being so, lets make it a parameter to our JavaScript function. Here's the result:

    function doItem(aItem) {
     aBase = '<html:rewrite forward="item"/>'; 
     HC_doOpenRemote(aBase + '?item=' + aItem,'preview','*','600','scrollbars','form'); 
    // --> 

Note that we only need to pass the item number (e.g. "117") to this function. The function then takes the base part of the URI and concaternates it with the query string and our parameter.

All that's left now is passing the parameter to the script. The item number would be passed to the page within a JavaBean, so we can use bean:write for that:

    <a href='javascript:doItem(<bean:write name="itemForm" property="item"/>)'>Item Number</a>

At runtime, this would resolve to

    <a href='javascript:doItem(117)'>Item Number</a>

Since the JavaScript is rewriting the URI, we don't have to worry about that part of it here, and can use a conventional hyperlink tag.

<h4>Whole Cloth Approach</h4>

You could also just write the entire script into the page from scratch:

    <bean:write name="fancyForm" property="javaScript" filter="off"/> 
    // --> 

This will write out whatever is returned by the String fancyForm.getJavaScript() method. This lets you create the JavaScript by any means necessary. The Struts Validator uses this approach to create a complex series of scripts that are rendered into the page from a single JSP tag.

Of course, any other element or HTML assets can also be created this way.

<h4>Rename Submit</h4>

Some JavaScripts may try to call the submit operation for a form. By default, the <html:submit> button is also named (surprise) submit. To avoid conflicts, give the submit button another name.

<h4>Formless Buttons</h4>

It is often useful to use a button to represent a hyperlink or JavaScript action. Problem is, the <html:form> tag expects each form to have a corresponding ActionForm bean. A hyperlink and many JavaScript actions don't need parameters and so don't need a form-bean The solution is to give the tag what it wants and define a simple form with no properties.

public class BlankForm extends ValidatorForm { // blank form };

This form can then be cited in the Struts configuration whenever a "formless" form is needed. For example, to provide a JavaScript back button:


     path="/Back" type="org.apache.struts.ForwardAction" 

JavaServer Page:

    <html:form action="/Back">
    <html:button property"page" onclick="history.go(-1)">DONE</html:button>

HTH - Ted.


Struts Tips  are excerpts from the book Java Web Development with Struts. The tips released twice weekly on the MVC-Programmers List. To subscribe, visit BaseBean Engineering.

About Ted. Ted Husted is an active Struts Committer and co-author of Java Web Development with Struts and Professional JSP Site Design. Ted also moderates the Struts mailing list and the JGuru Struts FAQ.

Copyright Ted Husted 2002. All rights reserved.


MVC-Programmers mailing list