Creating Java Server Pages Applications

Precautions

Before you begin to use this JSP toolkit, you should have read Defining data structures . The toolkit uses these "data objects" to read and write database tables.

Introduction

Encapsulation

There are lots of things in JSPs that may be encapsulated into Java objects. Most of all, all INPUT elements are suitable to be mirrored by appropriate objects. We do this analogously to the Swing JComponent objects. We group this components as "markupables", which means, that they can represent themselves in markup languages by implementing the method getCreationTag(). See de.must.markup.Markupable .

Concerning persistence, there is even much more benefit reachable by encapsulating logic. To avoid tiring and bug-causing getters and setters you may use database field connected markup components. See de.must.markup.Storable . Components implementing this interface are associated to a database field by naming table and column name when constructed and by triggering the primary key when loaded.

To delegate looping load and save methods over multiple components to the framework, grouping is supported. See de.must.markup.GroupOfStorables and de.must.markup.GroupOfMarkupables .

The Butler Principle

JSP should use beans, we have been told. Right, let's give them a name. We could name them server, but this term is already in use. What about butler? A butler subserves its master, and that's what this bean should do for its JSP: Give him the insouciance only to care about design.

Every JSP has one butler class. In the JSP, it's always called simply butler. Thus, we don't have to rename this object, if we reuse existing code for similar pages. These butler classes are associated via jspSession.getButler(). Why not via useBean? Cameleon OSP provides control over all butlers in your session to create them in an arbitrary sequence and to destroy them. E.g. it's profitable to first create the butler class, give him initial values like e.g. a where condition, and then call the JSP to use the existing butler.

Sample

JSP

<%@ include file="header.inc" %>

<%@ page import = "de.jugs.cookbook.jsp.CbpropButler" %>
<% CbpropButler butler = (CbpropButler)jspSession.getButler(CbpropButler.class); %>

<%@ include file="afterbf.inc" %>

<html>
<head>
   <title>Rezept-Eingabe</title>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <meta name="Author" content="Christoph Müller">
   <%@ include file="headtags.inc" %>
</head>
<body>

<h2>
Rezept-Eingabe</h2>

<table CELLSPACING=0 CELLPADDING=4 COLS=1 WIDTH="100%" >
<tr>
<td class="subtitle">Das geh&ouml;rt alles dazu</td>
</tr>
</table>

<p>
<form method="POST">
<table COLS=2 WIDTH="100%" >
<tr>
<td>Rezept-Bezeichung:</td><td><%=butler.rezeptBez%></td>
</tr><tr>
<td>Rezept-Typ:&nbsp;</td><td><%=butler.typ%> <%=butler.diabetiker%></td>
</tr><tr>
<td>Zutaten:</td><td><%=butler.zutaten%></td>
</tr><tr>
<td>Zubereitung:</td><td><%=butler.zubereit%></td>
</tr><tr>
<td>Quelle:</td><td><%=butler.quelle%></td>
</tr><tr>
<td>Vom:</td><td><%=butler.vom%></td>
</tr>
</table>

<p><%=butler.okButton%> <%=butler.cancelButton%>
</form>
</body>
</html>

The associated (butler) class:

/*
 * Public Domain Sample Code
 */
package de.jugs.cookbook.jsp;

import de.jugs.cookbook.DoCookbook;
import de.jugs.cookbook.DoType;
import de.must.markup.*;
import javax.servlet.http.HttpServletRequest;

/**
 * Devoted butler of the cookbook property administration JSP.
 * See super class JspButler for documentation.
 * @author Christoph Mueller
 */
public class CbpropButler extends JspButler {

  private DoCookbook doCookbook;
  private GroupOfStorables storables;

  public DataTextField rezeptBez;
  public DataComboBox typ;
  public DataCheckBox diabetiker;
  public DataTextArea zutaten;
  public DataTextArea zubereit;
  public DataTextField quelle;
  public DataDateField vom;
  public OkButton okButton;
  public CancelButton cancelButton;

  private int counter;

  public CbpropButler(SessionData sessionData) {
    super(sessionData);
    doCookbook = new DoCookbook();
    storables = new GroupOfStorables(doCookbook, sessionData);
    rezeptBez = storables.createTextField("RezeptBez");
    typ = storables.createComboBox(sessionData, "Typ", new DoType(), "TypBez");
    diabetiker = storables.createCheckBox("Diabetiker-Empfehlung", "Diabetiker");
    zutaten = storables.createTextArea("Zutaten");
    zubereit = storables.createTextArea("Zubereit");
    quelle = storables.createTextField("Quelle");
    vom = storables.createDateField("Vom");
    okButton = storables.createOkButton(sessionData);
    cancelButton = storables.createCancelButton(sessionData);
  }

  protected void handle(HttpServletRequest request) {
    storables.fetchValuesFromRequest(request);
if (okButton.wasPressed()) {
if (storables.inputCheckOk() && isInputAccepted()) {
storables.save();
goBack(); return;
}
} else if (cancelButton.wasPressed()) {
goBack(); return;
} else {
String idString = request.getParameter("ID");
if (idString != null) {
storables.loadValues(Integer.parseInt(idString));
} else {
storables.newInput();
}
}
  }

  private boolean isInputAccepted() {
    if (rezeptBez.getText().length() == 0) {
      setMessageToKeep("Rezeptbezeichnung muss gefüllt sein.");
      return false;
    }
    return true;
  }

}

Explanations

The sample shows how to create text fields, text areas, combo boxes and check boxes, load their values from database tables, presenting them and supporting rewriting data as changed by the user.

To support database connection please configure Global , it's a subclass of  de.must.middle.GlobalStd containing the specification to connect to the database.


© Copyright 2001-2004 Christoph Müller, Kärntner Str. 56, D-70469 Stuttgart, Germany, http://www.must.de