Wattle Software - producers of XMLwriter XML editor
 Home | Site Map 
XMLwriter
 Screenshots
 Features
 About Latest Version
 Awards & Reviews
 User Comments
 Customers
Download
 Download XMLwriter
 Download Plug-ins
 Download Help Manual
 Downloading FAQ
Buy
 Buy XMLwriter
 Pricing
 Upgrading
 Sales Support
 Sales FAQ
Support
 Sales Support
 Technical Support
 Submit a Bug Report
 Feedback & Requests
 Technical FAQ
Resources
 XML Links
 XML Training
 XMLwriter User Tools
 The XML Guide
 XML Book Samples
Wattle Software
 About Us
 Contact Details
Professional Java XML Programming with Servlets and JSP

Buy this book

Back Contents Next

Birthday Announcements with JSP and JavaMail

This is a toy application that has, we believe, the potential to get grown-ups interested. Suppose you have a group of people working together, and you want to build a spirit of community among them. One way to do that is to make sure that if today is someone's birthday then you let everyone know and send congratulations via email. So, you put together a table in your database that has everyone's name, birthday and email address. Every morning a friendly demon submits a form, and if there is a birthday on that day, everybody gets an email. (As you well know, it's very easy to overdo these things, and get everybody extremely annoyed at you for too much friendly email.)

 

The entry point to the application is birthdays.htm. It sets up the initial parameters, two of them in hidden input elements: bbcmd is set to login and dbOperation to BIRTHDAYLIST. Visible inputs can be used to customize the application in much the same way an initialization file is used in the QShell application we developed in the first chapters of the book. This is what birthdays.htm looks like:

 

 

After the initial form gets submitted, control is passed to the main JSP page, birthdays.jsp. It creates the BirthdayBean and sets its properties. One of those properties is bbcmd. That property determines what the bean will do. If the command is sendMail, the bean will send email, using the parameters set by the user in the form on the client. If the command is dbOperation, the bean will create a DBHandler object (unless it has already been created) and run the dbOperation. (Do you still remember DBHandler? That's the guy that handles all the interactions with the database using internal Query objects. It's still with us, after all these chapters, and is as useable out of a bean as it is out of a servlet.)

 

Suppose the user has submitted a database query asking for December 8 birthdays. The screen shot below shows the results returned by the database, and the email parameters set by the user:

 

 

If the user now selects and submits the sendMail command, the following email will be sent:

 

X-POP3-Rcpt: sasha@cs

Return-Path: <tomm@tommyers.colgate.edu>

Date: Thu, 28 Oct 99 09:05:43 -0400

From: tomm@tommyers.colgate.edu

To: sasha@cs.colgate.edu

Subject: December 8 Birthdays

 

Eli Whitney        1765-12-08 00:00:00   tom.myers@worldnet.att.net  

Jan Sibelius  1865-12-08 00:00:00   tom.myers@worldnet.att.net

 

The bean also sets its jspcmd property, and the rest of the application operates in a circle described in the preceding section. The jspcmd property determines the page returned to the user. If it is not an error or logout, then the page returned to the user contains a form; the user can specify the command to perform and submit the form, and so on. Our task now is to understand how it all works together. We will start with the client, move on to the JSP page, visit the bean, and follow its database and email connections. As we meander through the application, the following bean-centric diagram, showing the bean's inputs and outputs, may be useful in keeping track of where we are in the overall scheme of things:


 

Entry Point: birthday.htm

The entry point to the system is an HTML file that consists entirely of a single form.

 

<html><head><title>birthday.htm</title></head><body bgcolor="lightblue">

<h1>The Birthday Lister</h1>

<form name=theForm type=POST action="birthday.jsp">

 

Within that form, there are the following divisions:

 

two hidden inputs for bbcmd and dbOperation

two inputs for the database: username and password

a simple piece of JavaScript code to generate an input for Date with the value of the current date

two inputs for sending mail: return address and SMTP host

a textarea element with initialization data, in the same format as a QShell initialization file

 

The first of these divisions have already been mentioned; the second is completely trivial:

 

<input type=hidden name="bbcmd" value="login">

<input type=hidden name="dbOperation" value="BIRTHDAYLIST">
DB username, password:

<input type=text name="dbUser" value="name"><br>

<input type=password name="dbPwd" value="pwd">

 

The JavaScript code is a sequence of document.write() statements, to make it cross-browser. It creates a Date object that holds the current date and converts it to String in the yyyy-mm-dd format that Java likes:

 

<script>

    function dw(x){document.write(x);}

    var today=new Date();

    var todayStr=today.getFullYear()+"-"+

            (1+today.getMonth())+"-"+

            today.getDate();

    dw(todayStr);

    dw("<br>Compare birthdays with: ");

    dw("<input type=text name=when value=\"");

    dw(todayStr);

    dw("\">");

</script>


The inputs having to do with e-mail are, in a sense, self-explanatory; the way they work in JavaMail code will be discussed later. These two inputs create a great opportunity for mischief: imagine an immature and mean-spirited hacker writing a little program that submits the form 100 times using the e-mail of somebody they hate and 20 different SMTP servers. There are, and probably there will always be people like that among us, so in any kind of serious application, a JSP page that receives such a form should be password-protected.

 

Finally, the initial content of the textarea element contains initialization data in the familiar format. One new entry there is dateFormat so users can specify their own input date format, if necessary. (The output format will not be affected: it will always be JDBC "escape format", as defined in java.text.SimpleTextFormat.)

 

<br>EMail Return Address: <input type=text name=retaddr value="">

<br>SMTP host: <input type=text name=smtphost value="cs.colgate.edu">

<br>

<textarea name="initdefs" rows="5" cols="40">

dbDriver

sun.jdbc.odbc.JdbcOdbcDriver

dbName

jdbc:odbc:BIRTHDAYS

dateFormat

yyyy-MM-dd

dbQueries

LOOKUPALL,BIRTHDAYLIST,LOOKUPFROMWHEN,LOOKUPFROMWHO,ADD,DELETE,CREATE

...

CREATE

CREATE TABLE Birthdays(Who VARCHAR, When DATE, Addr VARCHAR);

</textarea>

<input TYPE=submit name="submit" value="submit">

</form></body></html>

 

The main thing to remember about all these input elements is that our BirthdayBean has properties with identical names, and at some point the main JSP page will say:

 

<jsp:setProperty name="bbean" property="*" />

 

As we discussed above, if you want all request parameters copied to bean properties of the same name, you code it as property="*".

The Main JSP page: birthday.jsp

You have already seen the beginning of birthday.jsp:

 

<html>

<head>

<title>Birthday JSP/Bean/DBHandler/Mail</title>

</head>

<body>

 

<%@ page import="java.util.*, MyNa.utils.*" errorPage="errorpage.jsp" %>

<jsp:useBean id="bbean" scope="session" class="birthday.BirthdayBean" />

<jsp:setProperty name="bbean" property="*" />


Since birthday.jsp is our main servlet for the application, we unload all processing to the bean, in order to keep the structure of the servlet clear. In particular:

 

we process the request in the bean, by calling its public processRequest() method

we have the bean process the current command, on the basis of the docmd property set in the user input

we produce output based on the value of the jspcmd property set by the bean. If the required output is more than a couple of lines long, we put it into an include file

 

Since much of birthday.jsp code has already been discussed, we show the rest of it in one piece:

 

<% bbean.processRequest(request); %>

<%

    bbean.doCommand(); // usually, this is all we need after setting properties

    String msgtext="";  // accumulate messages here, if needed.

    String select=bbean.getJspcmd();

    if("logout".equals(select))

    {

%>

    Goodbye, come again soon.

<%

    }

    else if("error".equals(select))

    {

%>

    Something went wrong: <%= bbean.getErrorString() %>

    Click your back button and try again, or tell us.

<%

    }

        else if("change".equals(select))

    {

%>

        We changed <%= bbean.getNumberAffected() %> rows.

        <%@ include file="continue.jsp" %>

<%

    }

    else if("msgsent".equals(select))

    {

%>

        Congratulations, you sent a message.

<%@ include file="continue.jsp" %>

<%

    }

    else if("list".equals(select)){ %>

     <%@ include file="listall.jsp" %>

<%

    }


 

    else if("birthdaylist".equals(select))

    {

%>

    <%@ include file="birthdaylist.jsp" %>

<%

    }

    else

    {

%>

    Unimplemented command [<%= select %>]; how did this happen?

<%

    }

%>

</body>

</html>

 

The possible values of select (i.e. of jspcmd) are: logout, error, change, msgsent, listall and birthdaylist. The difference between the last two is that listall lists the entire contents of the birthdays table in the database, while birthdaylist lists only the records matching the specified date. The corresponding output files both include the file continue.jsp. Let's take a look at the output.

Output Template Files

Apart from error.jsp, there are three output files, birthdaylist.jsp, listall.jsp and continue.jsp. The first two are very similar: they show a typical JSP loop to output a table. Here is birthdaylist.jsp:

 

this is the file birthdaylist.jsp,

<%

    String[][]rows=bbean.getResultTable();

    if(rows.length==0){

%>

    Sorry, nobody has a birthday coinciding with <%= bbean.getWhen() %>.

<%

    }

    else

    {

%>

        Birthday Announcements!<br>

        <table border="1">

<%

        for(int i=0;i<rows.length;i++)

    {

%>

    <tr>

<%

        String[] row=rows[i];

        for(int j=0;j<row.length;j++)

        {

            msgtext+=row[j]+"\t";

%>

              <td><%= row[j] %></td>

<%

         }

%>

    </tr>

    <% msgtext+="\n"; } %>

    </table>

<%

    }

%>

 

    <%@ include file="continue.jsp" %>

Continue.jsp

This file outputs a form whose ACTION is birthday.jsp, to complete the circle. It's almost completely HTML; the only JSP element is an expression, <%= msgtext %>, that we place in the textarea as a possibly helpful hint to the user. Otherwise, it's just an HTML form with two SELECT elements and several text inputs; the SELECT elements are for bbcmd and dbOperation. We precede the form with a simple JavaScript function to validate its input values before sending them to the server.

 

In outline, then, continue.jsp consists of two large sections:

 

<script>

   <!-- two Javascript functions, including onsub() -->

</script>

<form name="theForm" action="birthday.jsp"

        method="post" onsubmit="return onsub()">

   <!-- the form as described -->

</form>

 

We present the two sections in order.

Two Javascript Functions

The onsub() method checks two conditions: that the toaddr and subject inputs are filled, and that database queries have the right number of parameters. For each condition, there is a supporting function that checks it. In order to check the right number of arguments, we set up a JavaScript object argCount, which associates a query name with the number of arguments for that query. (As you may know, Javascript objects can be used as associative arrays. For more details, see our JavaScript Objects, Wrox Press 1998, ISBN: 1861001894.)

 

<script>

    var argCount={LOOKUPFROMWHEN:1,LOOKUPFROMWHO:1,ADD:3,DELETE:1};

    function onsub()

    {

        var theForm=window.document.theForm;// get reference to the form

        var theCmd=theForm.bbcmd.value;     // get the value of bbcmd

        if(theCmd=="logout")return true;    // if logout, submit the form

        if(theCmd=="send")

          return sendOk(theForm);// check sendOk condition

        return doDBOk(theForm);  // it's a db query:check doDBOk condition

    }


 

    function sendOk(theForm)

    {

        if(""==theForm.toaddr.value)

        {

            alert("must fill in toaddress");

            return false;

        }

        if(""==theForm.subject.value)

        {

            alert("must fill in subject");

            return false;

        }

        return true;

    }

    function doDBOk()

    {

        var theOp=theForm.dbOperation.value;

        var N=argCount[theOp]; // retrieve number of arguments

        if(!N)N=0; // if null, set it to 0

        theForm.ParameterMax.value=N;

        for(var i=1;i<=N;i++)
        {

            if(""==theForm["Parameter"+i].value)

            {

                alert("must fill in Parameter"+i);

                return false;

            }
        }

        if(theOp=="BIRTHDAYLIST") // param passed as "when"

            theForm.when.value=theForm.Parameter1.value;

        return true;

    }

</script>

The Form

And here is the form; its onsubmit attribute is a call on onSub(). As we said, the only JSP element in it (and the entire page) is an expression inside the text area:

 

<form name="theForm" action="birthday.jsp"

        method="post" onsubmit="return onsub()">

<input type=hidden name=ParameterMax value="0">

<input type=hidden name=when>

 

Select a BirthdayBean Command:

<select name=bbcmd size=1>

<option value="dodb" selected>doDB Op</option>

<option value="send">send message</option>

<option value="logout">logout</option>

</select>

<br>


 

Select a Database Op:

<select name=dbOperation size=1>

<option value="LOOKUPALL" selected>show the table</option>

<option value="BIRTHDAYLIST">birthday list for yyyy-MM-dd date</option>

<option value="LOOKUPFROMWHEN">look up a specific date</option>

<option value="LOOKUPFROMWHO">look up a specific person</option>

<option value="ADD">add a (who,when,addr) entry in dbase</option>

<option value="DELETE">delete a person (by name)</option>

</select>

<br>

<input type=submit>

<br>

Parameters for DB Queries:

<br><input type=text name=Parameter1 size=10 value="">

<br><input type=text name=Parameter2 size=10 value="">

<br><input type=text name=Parameter3 size=10 value="">

<br>

Or you can send mail. <br>

Send to: <input type=text name=toaddr value="" size=20><br.

about: <input type=text name=subject value="" size=20>

<br>

<textarea name=msgtext rows=10 cols=50>

<%= msgtext %>

</textarea></form>

 

This concludes continue.jsp. We have now seen all the inputs and outputs, and the entry point and the main JSP "servlet page". What we have not seen is the Java code that makes it all work. Time to open up the bean.

Inside the Bean: BirthdayBean.java

The bean works with the familiar components, Env and DBHandler, to do database access, and with new email components that are tucked away in MyNa.utils.MiscMail.java. For now, let's concentrate on the overall structure. We have, as usual:

 

imports and declarations

a null constructor, getXXX() and setXXX() methods

processRequest() and doCommand() methods called by the JSP page

"command methods": doLogout(), sendMessage() and doDB() (with pruneResults())

 

We take them up in order.


Imports and declarations

Imports are self-explanatory, but remember that MyNa.utils.* now includes MiscMail:

 

package birthday;

 

import javax.servlet.http.*;

import java.util.Vector;

import java.io.BufferedReader;

import java.io.StringReader;

import java.util.Enumeration;

import javax.mail.MessagingException;

import MyNa.utils.*;

 

public class BirthdayBean

{

    String bbcmd = null; //BirthdayBeanCommand from JSP specifies action

    String jspcmd = null; // JSPCommand from BBean specifies display

 

    // variables for databases: the fields of the table are WHO, WHEN and RETADDR

    String who = null;

    String when = null;

    String retaddr = null;

 

    // variables for mail connection

    String toaddr = null;

    String smtphost = null;

    String mailuser = null;

    String subject = null;

    String msgtext = null;

 

    // variables for Env and DBHandler; initdefs comes from client

    String initdefs = null;

    Env env = null;

    DBHandler dbh = null;

 

    // outputs

    String errorString = null;

    String[][] resultTable = null;

    String numberAffected = null;    // if query returns a number

 

The first two declarations, bbcmd and jspcmd, have been explained earlier.

Constructor, Getters and Setters

Most of this is fairly trivial code, but some of it sets jspcmd:

 

public BirthdayBean()

{

}

 

public void setBbcmd(String S)

{

    bbcmd = S;

}


 

public void setWhen(String S)

{

    if(null != S)

    {

        when = S;

    }

}

 

public void setRetaddr(String S)

{

    retaddr = S;

}

 

public void setToaddr(String S)

{

    toaddr = S;

}

 

public void setSmtphost(String S)

{

    smtphost = S;

}

 

public void setSubject(String S)

{

    subject = S;

}

 

public void setMsgtext(String S)

{

    msgtext = S;

}

 

public void setInitdefs(String S)

{

    initdefs = S;

}

 

// set methods that also set jspcmd

public void setNumberAffected(String S)

{

    jspcmd = "change";

    numberAffected = S;

}

 

public void setResultTable(String[][] S)

{

    jspcmd = "list";

    resultTable = S;

}

 

public void setErrorString(String S)

{

    errorString = S;


 

    if(null != S && S.length() > 0)

    {

        jspcmd = "error";

    }

}

 

// get methods

public String getErrorString()

{

    return errorString;

}

 

public String getNumberAffected()

{

    return numberAffected;

}

 

public String getWhen()

{

    return when;    // to a new jsp page

}

 

public String[][] getResultTable()

{

    return resultTable;

}

 

public String getJspcmd()

{

    return jspcmd;

}

 

public Env getEnv()

{

    return env;

}

 

public boolean shouldDoDB()

{

    return "login".equalsIgnoreCase(bbcmd) || "dodb".equalsIgnoreCase(bbcmd);

}

processRequest() and doCommand()

What processRequest() does depends on the value of bbcmd. The possible values are:

 

login (sent from the entry HTML page)

dodb

sendmsg

 and logout (sent from the continue.jsp page)


If the value of bbcmd is sendmsg or logout then the processRequest() method does nothing. With either of the first two options, the bean will have to do database access, either to establish a connection and a login (for "login"), or to run a query (for "dodb"). You will see from the second last line of the code above that shouldDoDB() returns exactly the boolean value of the disjunction (in English) "bbcmd equals 'login' or bbcmd equals 'dodb'".

 

So, in either of those two cases we have to process a new Request, which means re-initializing the Env that holds request information. This is what is done in the first part of the method: a new Env is created from Request, and information from initdefs is added, if it is not null. (It will be non-null only if we are processing the initial HTML file that has an initdefs textarea element.)

 

public void processRequest(HttpServletRequest request)

{

    try

    {

        if(shouldDoDB())

        {

 

            // set up env with Request and initdefs info

            try

            {

                env = new Env(request);

            }

            catch(java.lang.NullPointerException e)

            {

                setErrorString("null in Env init");

                return;

            }

            // end create Env from Request

 

            if(null == env)

            {

                setErrorString("can't initialize env from request");

            }

 

            else

            {

                if(null != initdefs)

                {

                    // add initdefs to Env

                    StringReader sr = new StringReader(initdefs);

                    BufferedReader brin = new BufferedReader(sr);

                    env.addBufferedReader(brin);

                }

                // end add initdefs to Env

            }

 

        }    // end shouldDoDB


If we are, indeed, doing the "login" command then we also have to establish a database connection and initialize queries, all of which is wrapped into a DBHandler object, created from the Env:

 

        try

        {

            if("login".equalsIgnoreCase(bbcmd))

            {

                // login to database

                dbh = new DBHandler(env);

            }

        }

 

        catch(java.lang.NullPointerException e)

        {

             setErrorString("null in DBHandler init");

             return;

        }    // end create DBHandler

 

    } // end try

 

    catch(ParseSubstException e)

    {

        setErrorString("bad initdefs" + e);

    }

 

    catch(Exception e)

    {

        setErrorString("dbhandler failure: " + e);

    }

 

}

 

The doCommand() method does not really do any commands itself, just dispatches the action to the right method:

 

public void doCommand()

{

    if("logout".equalsIgnoreCase(bbcmd))

    {

        doLogout();

    }

    else

    {

        if("send".equalsIgnoreCase(bbcmd))

        {

            sendMessage();

        }

    }

    else

    {

        if(shouldDoDB())

        {

            doDB();

        }

    }


 

    else

    {

        setErrorString("unrecognized command [" + bbcmd + "]");

    }

}

 

These two methods are public and called from the outside by the JSP page. The rest are the bean's internal affairs.

Command Methods

The methods that do specific commands have one thing in common: they set the jspcmd variable, so the JSP page knows what to include for output. Otherwise, they each do their own tasks. The doLogout() method closes the DBHandler:

 

public void doLogout()

{

    jspcmd = "logout";

    try

    {

        if(dbh != null)

        {

            dbh.close();

        }

    }

    catch(java.sql.SQLException e)

    {

        setErrorString("query failure: " + e);

    }

}

 

Note that the sendMessage() method does a fairly sophisticated thing, but it is hidden in the static sendMail() method of our MiscMail utility class. The method takes five arguments, all of them strings: a mail host name (such as "center.colgate.edu"), and four components of the message: from, to, subject and body.

 

public void sendMessage()

{

    try

    {

        MiscMail.sendMail(smtphost, retaddr, toaddr, subject, msgtext);

        jspcmd = "msgsent";

    }

    catch(MessagingException e)

    {

        setErrorString("send failure: " + e);

    }

}


Finally, doDB() goes to the database and comes back either with an integer or a table of results, stored in the Env. It starts by clearing previous values, if any, then runs the query. For the BIRTHDAYLIST query, an additional pruning action is necessary, as explained below:

 

public void doDB()

{

    env.remove("NumberOfRowsAffected");

    env.remove("ResultTable");

 

    try

    {

        dbh.getQueryResult(env);

    }

    catch(java.sql.SQLException e)

    {

        setErrorString("query failure: " + e);

    }

 

    String n = env.getStr("NumberOfRowsAffected");

    if(null != n)

    {

        // an update query

        setNumberAffected(n);

        return;

    }

 

    setResultTable((String[][])env.get("ResultTable"));

    if("BIRTHDAYLIST".equalsIgnoreCase(env.getStr("dbOperation")))

    {

        pruneResults();

    }

}

Pruning the Results

In our Birthdays database, the "when" field is of Date data type, converted from String by DBHandler. Because of this, we cannot query on month and day in database-independent ways. (Database-dependent solutions are certainly available, e.g. the use of embedded Visual Basic in Access queries.) So, if the query is BIRTHDAYLIST, we return the entire table and have the bean prune it by pruneResults():

 

public void pruneResults()

{

    // "when" field is a String in yyyy-mm-dd format, e.g. 1999-03-25

    // we prune the result table so that only birthday matches survive.

 

    jspcmd = "birthdaylist";


 

    if(resultTable.length == 0)

    {

        return;

    }

    String monthDay = when.substring(4); // "-03-25 "

    Vector v = new Vector();

 

    for(int i = 0; i < resultTable.length; i++)

    {

        String S = resultTable[i][1]; // the "When" field;

        if(null == S)

        {

            continue;

        }

        if(S.indexOf(monthDay) != 4)

        {

            continue;

        }

        v.addElement(resultTable[i]);

    }

 

    resultTable = new String[v.size()][];

    for(int i = 0; i < v.size(); i++)

    {

        resultTable[i] = (String[])v.elementAt(i);

    }

 }

 

}                                                   // end of BirthdayBean class

 

Obviously, this pruning solution can only work for small tables; for a table of unknown (and possibly huge) size, we would have to move the pruning up the food chain, either all the way to the database, or to the RowEnumeration process. In order to move the pruning to the database, we would split the Date field into three number fields, year, month and day, and query on month and day. Alternatively, we could prune the rows emitted from the ResultSet, by extending our RowEnumeration class to PrunedRowEnumeration:

 

public RowEnumeration pruneEnum(RowEnumeration re, String when)

        throws SQLException

{

    // when == "1999-03-25", march 25 1999, jdbc escape format;

    String monthDay = when.substring(4);    // "-03-25";

    return new PrunedRowEnumeration(re, "When", monthDay, 4);

}

 

public class PrunedRowEnumeration extends RowEnumeration

{

    String fieldName;

    String match;

    int offset;

    // we produce only those elements of re where fieldname

    // matches match beginning at offset.


 

    public PrunedRowEnumeration(RowEnumeration re, String fieldName,

            String S, int N) throws SQLException

    {

        super();

        initFromRowEnumeration(re);

        this.fieldName = fieldName;

        this.match = S;

        this.offset = N;

    }

 

    public boolean hasMoreElements()

    {

        boolean gotAnother = true;

        while((gotAnother = super.hasMoreElements()))

        {

            String val = ((Env)nextElement()).getStr(fieldName);

            if(val.substring(offset).startsWith(match))

            {

                continue;

            }

        }

        return gotAnother;

    }

}

 

The JSP presentation code would then loop through a RowEnumeration, completely unaware that it was actually a PrunedRowEnumeration. Generalizations of this solution to include regular-expression matching and filtering are quite possible but outside the scope of this book.

From here...

This concludes the Birthday application. Its main point is not the content of the commands it can carry out, but rather the overall structure: the main JSP page that acts as a servlet; a bean that carries out its commands and sets up a selector for output; included template JSP pages for output that contain a form whose action takes us back to the main JSP page. We will reproduce this structure, with more meaningful content, in the application of the next chapter.

 

You may feel a little disappointed that we have said nothing about how JavaMail works. Not to worry: the next application will use JavaMail in a more comprehensive way, and we'll show you all the details.

JSP vs. SUBST Mini-Language for Output Templates

Before we close this chapter, we would like to draw some comparisons between JSP pages and our SUBST mini-language. You probably have customers who could generate new QShell applications; in other words, they could copy and modify HTML or XML templates in some limited language like the SUBST mini-language we developed earlier, and they are comfortable with defining new database queries. It is not at all obvious that they will be able and willing to work with something like:


 

<% bbean.doCommand(); String msgtext="";

    String select=bbean.getJspcmd();

    if("logout".equals(select))

    {

%>

 

    Goodbye, come again soon.

 

<%  

    }

    else if("error".equals(select))

    {

%>                                 

 

Even if willing to give it a try (after all, you might just suggest that they change the text in between %> and <% marks) will they persevere after the first time that a typo evoked a Java compiler error message? This is an empirical question, and the answer can only come from experience with using JSP in products that are delivered to end users. In the meantime, we remain a little skeptical. JSP is great stuff for Java programmers. It is a big timesaver when you are developing servlets. It can be wonderful for joint projects involving non-programmers. However, it is an open question whether or not it is a good tool for the development of specialized languages in which non-programmers can express their specialized knowledge.

 


Back Contents Next
©1999 Wrox Press Limited, US and UK.

Buy this book



Select a Book

Beginning XML
Beginning XHTML
Professional XML
Professional ASP XML
Professional XML Design...
Professional XSLT...
Professional VB6 XML
Designing Distributed...
Professional Java XML...
Professional WAP

© Wattle Software 1998-2019. All rights reserved.