Java™ Servlet Technologie
zurück weiter
Java™ Servlet Technologie

Anwendungsbeispiel


Das Servlet EditProducer

Zielstellung

Das Servlet EditProducer hat die Aufgabe, die in der Datenbank enthaltenen Herstellerdaten zu generieren, zu verändern und zu entfernen. Der Aufruf erfolgt dabei über das entsprechende Menü der Webseite zur Verwaltung der Produktkatalog-Daten. Da das Menü zur Herstellerverwaltung zwei Optionen bietet, muß im Servlet eine Fallunterscheidung entsprechend der Auswahl getroffen werden. Diese beiden Optionen beinhalten einerseits die Formularansicht zur Erstellung und zum Löschen von Herstellern, andererseits eine Formularansicht zum Bearbeiten der zu den Herstellern gehörenden Adreßdaten. Einem Hersteller können dabei beliebig viele Adressen zugeordnet werden, die jederzeit editiert werden können.

Um die Konsistenz der Datenbank zu sichern, ist das Löschen von Herstellern nur dann möglich, wenn ihnen weder Adressen noch Produkte zugeordnet sind. Gegebenenfalls sind diese vorm Entfernen von Herstellern zuerst selbst zu entfernen.

Umsetzung

Zur Umsetzung der angesprochenen Funktionalitäten muß zunächst das Servlet EditProducer generiert werden. Hierzu wird wiederum die Klasse HttpServlet erweitert. Die Methoden zur Initialisierung eines Servlets und Beendigung eines Servlets werden hier exakt genauso benutzt, wie es beim Servlet Catalog beschrieben wurde. Deshalb wird an dieser Stelle nicht nochmals darauf eingegangen, sondern sofort mit der Beschreibung der Verarbeitung der Client-Anfrage begonnen.

Zur Fallunterscheidung der gewünschten Aktionen wird im versteckten Feld producer des Formulars mittels JavaScript vermerkt, ob die Option Hersteller hinzufügen/entfernen (Wert gleich 1) oder Herstellerdaten bearbeiten (Wert gleich 2) ausgewählt wurde. Der Wert eines weiteren versteckten Formularfeldes namens choice legt innerhalb dieser beiden Optionen die möglichen Aktionen fest (z.B. Hersteller hinzufügen, Herstelleradresse bearbeiten, ...). Die einzelnen Belegungsmöglichkeiten dieser Felder und deren Bedeutung werden im nachfolgenden Quell-Code ersichtlich.


    // Formualr-Feldnamen innerhalb der HTML-Seite zur Adreßbearbeitung
    private static String[] fieldNames = {"ADID","Name","Name2","Street","Number","ZIP","City","State","Country","Fon","Fax","EMail","URL"};

    // Spaltennamen für SQL-Abfrage zur Adreßbearbeitung
    private static String[] columnNames = {"ADID","NAME","NAME2","STRASSE","NUMMER","PLZ","STADT","BUNDESLAND","LAND","TELEFON","FAX","E_MAIL","INTERNETADRESSE"};

    // String-Array zur Aufnahme der Spaltenwerte aus dem HTML-Formular zur Adreßbearbeitung
    private String[] values = {"","","","","","","","","","","","",""};

    // Verarbeitung der Client-Anfrage
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        Vector product = new Vector();
        Vector address = new Vector();
        String producers = "";
        String producerName = "";
        String producer_id = "";
        String address_id = "";
        // öffnenter Tag der Adreß-Auswahlbox
        String addresses = "<SELECT name=\"addresses\" width=\"280\" style=\"width:280px\"></SELECT>";
        // Parameter für Eingabefelder im Adreßformular (nicht editierbar)
        String disabled = " disabled";
        String action = "";
        String filename = "";

        // globale Fehlervariable initialisieren
        noError = true;
        // Eingabefelder zur Adressbearbeitung initialisieren
        for (int i=0; i<columnNames.length; i++) address.addElement(""); 
        // Parameter "producer_choice" der Navigationsseite abfragen
        String producer = request.getParameter("producer_choice");
        // Parameter "choice" der Navigationsseite abfragen
        String choice = request.getParameter("choice");
        // wenn Hersteller-ID im Formular existiert
        if (producer != null) {
            // neuen Datensatz anlegen
            if (producer.equals("1")) {
                // vorgefertigte HTML-Datei definieren
                // absolute Pfadangabe muß bei Verwendung angepaßt werden
                filename = "/export/pub/jakarta-tomcat-4.0.3/webapps/adia/servlets/producer-create.html";
                // wenn Auswahl aus Formular ermittelt werden konnte
                if (choice != null) {
                    // Hersteller hinzufügen
                    if (choice.equals("1")) {
                        // neue Hersteller-ID aus Formular ermitteln
                        producer_id = request.getParameter("pid");
                        // neuen Herstellernamen aus Formular ermitteln
                        producerName = request.getParameter("name");
                        if ((producer_id != null) && (producerName != null)) {
                            // Methode wird nachfolgend noch genauer beschrieben
                            noError = insertProducer(producer_id, producerName);
                        }
                    }
                    // Hersteller entfernen
                    else if (choice.equals("2")) {
                        // Hersteller-ID aus Formular ermitteln
                        producer_id = request.getParameter("producers");
                        // Methode wird nachfolgend noch genauer beschrieben
                        if (producers != null) noError = deleteData("DELETE FROM hersteller WHERE hid=" + producer_id);
                    }
                }
            }
            // bestehenden Datensatz bearbeiten
            else if (producer.equals("2")) {
                // vorgefertigte HTML-Datei definieren
                // absolute Pfadangabe muß bei Verwendung angepaßt werden
                filename = "/export/pub/jakarta-tomcat-4.0.3/webapps/adia/servlets/producer-edit.html";
                // Hersteller-ID aus Formular ermitteln
                producer_id = request.getParameter("producer_id");
                if (producer_id == null) producer_id ="";
                // wenn Hersteller-ID ermittelt werden konnte
                if (!producer_id.equals("")) {
                    // akt. Herstellername aus Client-Anfrage abspeichern, da HTML-Seite komplett infolge Neuaufbau rekonstruiert werden muß
                    if (request.getParameter("producerName") != null) producerName = request.getParameter("producerName");
                    // Auflistung weiterer Herstellerparameter (Aufruf aus Bearbeitungsformular selbst)
                    address_id = request.getParameter("addresses");
                    if (address_id == null) address_id = "";
                    // Name updaten
                    if (choice != null) {
                        // Herstellername modifizieren
                        if (choice.equals("1")) {
                            // Methode wird nachfolgend noch genauer beschrieben
                            noError = updateProducerName(producerName, producer_id);
                        }
                        // gewählte Adresse zum Bearbeiten auflisten
                        else if (choice.equals("2") && noError) {
                            // Methode wird nachfolgend noch genauer beschrieben
                            address = listAddress(address_id);
                            // Variable beschreibt den Zustand der Eingabefelder des dynamisch genrierten Formulars (können also editiert werden)
                            disabled = "";
                            // Aktion wird im zu generierenden Formular eingetragen, um beim nächsten Aufruf des Servlets bei der Fallunterscheidung 
                            // die Absicht zum Modifizieren der Adreßdaten erkennen zu können
                            action = "update";
                        }
                        // neue Adresse hinzufügen bzw. aktualisieren, wenn bisher kein Fehler vorliegt
                        else if (choice.equals("3") && noError) {
                            // Parameter "action" der Navigationsseite abfragen
                            action = request.getParameter("action");
                            // wenn dieser Parameter nicht NULL ist
                            if (action != null) {
                                // neue Adreßdaten einfügen
                                if (action.equals("insert")) {
                                    // Methode wird nachfolgend noch genauer beschrieben
                                    noError = insertAddress(producer_id, request);
                                }
                                // bestehende Adreßdaten modifizieren
                                else if (action.equals("update")) {
                                    // Methode wird nachfolgend noch genauer beschrieben
                                    noError = updateAddress(address_id, request);
                                }
                            }
                        }
                        // bestehende Adresse entfernen, wenn bisher kein Fehler vorliegt
                        else if (choice.equals("4") && noError) {
                            // Methode wird nachfolgend noch genauer beschrieben
                            noError = deleteData("DELETE FROM adresse WHERE adid=" + address_id);
                        }
                    }
                    // Adressen des Herstellers auflisten, wenn bisher kein Fehler vorliegt
                    if (noError) {
                        // Methode wird nachfolgend noch genauer beschrieben
                        addresses = listAddresses(producer_id, address_id);
                    }
                }
            }
            // Herstellerliste erzeugen, wenn bisher kein Fehler vorliegt
            if (noError) {
                // Methode wird nachfolgend noch genauer beschrieben
                producers = listProducers(producer_id);
            }
        }
        // Fehler, weil Hersteller-ID nicht im Formular existiert
        else {
            noError = false;
            error = "Hersteller-ID = null";
        }

        // Erzeugung und Ausgabe der HTML-Seite
        try {
            // wenn keine Fehler aufgetreten sind
            if (noError) {
                // vorgefertigte HTML-Seite einlesen
                page = pageGen.readPage(filename);
                // Platzhalter ersetzen
                page = pageGen.replaceParam(page,producers,"@producers@");
                // wenn HTML-Seite zum Ändern von Herstellerdaten generiert wird
                if (producer.equals("2")) {
                    page = pageGen.replaceParam(page,producerName,"@producerName@");
                    page = pageGen.replaceParam(page,addresses,"@addresses@");
                    page = pageGen.replaceParam(page,producer_id,"@producer_id@");
                    page = pageGen.replaceParam(page,disabled,"@disabled@");
                    page = pageGen.replaceParam(page,action,"@action@");
                    // Platzhalter der Adreßdetails ersetzen
                    for (int i=0; i<fieldNames.length; i++) {
                        // wenn Adreßdaten ermittelt werden konnten
                        if (address != null) {
                            page = pageGen.replaceParam(page,(String)address.elementAt(i),"@adr" + fieldNames[i] + "@");
                        }
                        // ansonsten entfernen der Platzhalter für Adreßdetails
                        else {
                            page = pageGen.replaceParam(page,"","@adr" + fieldNames[i] + "@");
                        }
                    }
                }
            }
            // Fehlerausgabe
            else {
                // absolute Pfadangabe muß bei Verwendung angepaßt werden
                page = pageGen.readPage("/export/pub/jakarta-tomcat-4.0.3/webapps/adia/servlets/error.html");
                page = pageGen.replaceParam(page,error,"@error@");
            }
        }
        // Fehlerbehandlung
        catch (Exception e) {
            page = e.toString();
        }
        // Ergebnisausgabe an den Client
        out.println(page);
    }
    
Die vorgefertigten HTML-Seiten mit den Platzhaltern können hier für die Bearbeitung der Herstellerdaten und hier für die Bearbeitung der Herstelleradressen betrachtet werden.

Im folgenden sollen nun die acht Methoden des Servlets EditProduct beschrieben werden, die in der zuvor beschrieben doGet(HttpServletRequest request, HttpServletResponse response)-Methode nicht näher beschrieben wurden. Als erstes wäre da die Methode listProducers(String producer_id). Sie generiert ein Auswahlbox mit sämtlichen Herstellernamen. Durch den Übergabeparameter kann ein bestimmter Hersteller anhand seiner ID in der Auswahlbox vorselektiert werden. Der Rückgabewert dieser Methode gibt nach außen hin einen aufgetretenen Fehler zu erkennen, falls er dem NULL-Wert entspricht. Außerdem wird beim Auftreten eines Fehlers auch die globale Fehlervariable noError mit dem Wahrheitswert FALSE belegt.


    // Herstellernamen in einer SELECT-Box auflisten
    private String listProducers(String producer_id) {
        Vector producers = new Vector();
        String result = "";
        // Parameterliste für SELECT-Tag definieren
        String[] args = {"name=\"producers\" width=\"200\" style=\"width:200px\" onChange=\"changeMenu();\""};

        try {
            // Parameterliste für Abfrage definieren
            String[] param1 = {"HID","NAME"};
            // Abfrage ausführen
            producers = dbcon.OraDBgetResult("SELECT * FROM hersteller", param1, 0);
            // Formatierung ausführen
            result = pageGen.formatSelect(producers, args, producer_id, 1);
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            noError = false;
            result = null;
            error = e.toString();
        }
        // formatierten String zurückgeben
        return result;
    }
    
Eine weitere Methode namens listAddresses(String producer_id, String address_id) dient der Erzeugung einer Auswahlbox, welche sämtliche Herstellernamen enthält. Während der Parameter producer_id die Hersteller-ID beinhaltet, für welche die zugehörigen Adressen aufgelistet werden sollen, kann über den Parameter address_id eine Adresse mit der entsprechenden Adreß-ID in der Auswahlbox vorselektiert werden. Der Rückgabewert dieser Methode gibt nach außen hin einen aufgetretenen Fehler zu erkennen, falls er dem NULL-Wert entspricht. Außerdem wird beim Auftreten eines Fehlers auch die globale Fehlervariable noError mit dem Wahrheitswert FALSE belegt. Nachfolgend der Quell-Code für diese Methode.

    // Herstellernamen in Auswahlbox auflisten
    private String listAddresses(String producer_id, String address_id) {
        Vector addresses = new Vector();
        Vector temp = new Vector();
        String result = "";
        String adr = "";
        // Parameterliste für SELECT-Tag definieren
        String[] args = {"name=\"addresses\" width=\"280\" style=\"width:280px\" onChange=\"disableComponents(true);\""};
        int anz = 0;

        try {
            // Parameterliste für Abfrage definieren
            String[] param1 = {"ADID","PLZ","STADT","STRASSE","NUMMER"};
            // Abfrage ausführen
            temp = dbcon.OraDBgetResult("SELECT adid,plz,stadt,strasse,nummer FROM adresse WHERE hid=" + producer_id, param1, 0);
            // wenn Ergebnismenge nicht leer
            if (temp != null) {
                // Umwandlung von PLZ, Stadt, Strasse und Nummer zu einem String
                String[] separator = {" ",", "," ",""};
                // Anzahl aller Listeneinträge ermitteln
                anz = temp.size();
                // alle Einträge verarbeiten
                for (int i=0; i<anz; i += 5) {
                    adr = "";
                    // jeweils 5 Einträge gehören zu einer Adresse
                    // Adresse zusammenfügen
                    for (int j=1; j<5; j++) {
                        // wenn String in der Liste an Stelle j nicht leer ist
                        if (!((String)temp.elementAt(i+j)).equals("")) adr += (String)temp.elementAt(i+j) + separator[j-1];
                    }
                    // ID der Adresse als ersten Wert eintragen
                    addresses.addElement(temp.elementAt(i));
                    // zusammengefügte Adresse danach einfügen
                    addresses.addElement(adr);
                }
            }
            // Formatierung ausführen
            result = pageGen.formatSelect(addresses, args, address_id, 1);
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            noError = false;
            result = null;
            error = e.toString();
        }
        // formatierten String zurückgeben
        return result;
    }
    
Die Methode listAddress(String address_id) liefert ein Vector()-Objekt zurück, welches die gesamten Daten einer bestimmten Herstelleradresse enthält. Der Parameter address_id bezeichnet dabei die Adreß-ID der gesuchten Adreßdaten. Der Rückgabewert dieser Methode gibt nach außen hin einen aufgetretenen Fehler zu erkennen, falls er dem NULL-Wert entspricht. Außerdem wird beim Auftreten eines Fehlers auch die globale Fehlervariable noError mit dem Wahrheitswert FALSE belegt. Nachfolgend der zugehörige Quell-Code.

    // Details einer Adresse ermitteln und als Vector()-Objekt zurückgeben
    private Vector listAddress(String address_id) {
        Vector result = new Vector();

        try {
            // Abfrage ausführen
            result = dbcon.OraDBgetResult("SELECT * FROM adresse WHERE adid=" + address_id, columnNames, 0);
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            noError = false;
            result = null;
            error = e.toString();
        }
        // Ergebnis zurückgeben
        return result;
    }
    
Zum Modifizieren eines Herstellernamen wird die Methode updateProducerName(String producerName, String producer_id) bereitgestellt. Während der Parameter producer_id die Hersteller-ID des zu modifizierenden Herstellernamen bezeichnet, enthält der Parameter producerName den neuen Herstellernamen. Der Rückgabewert dieser Methode gibt nach außen hin zu erkennen, ob die Operation erfolgreich war, oder ob ein Fehler aufgetreten ist. Nachfolgend der zugehörige Quell-Code.

    // Herstellername modifizieren
    private boolean updateProducerName(String producerName, String producer_id) {
        try {
            // Update ausführen
            int count = dbcon.OraDBexecuteUpdate("UPDATE hersteller SET name='" + producerName + "' WHERE hid=" + producer_id);
            // Mißerfolg melden, falls nichts modifiziert werden konnte
            if (count == 0) return false;
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            error = e.toString();
            return false;
        }
        // Erfolg melden
        return true;
    }
    
Die Methode insertProducer(String pid, String name) dient zum Hinzufügen neuer Hersteller zur Datenbank. Dabei beinhaltet der Parameter pid die neue Hersteller-ID und name den neuen Herstellernamen. Der Rückgabewert dieser Methode gibt nach außen hin zu erkennen, ob die Operation erfolgreich war, oder ob ein Fehler aufgetreten ist. Nachfolgend der zugehörige Quell-Code.

    // neuen Hersteller einfügen
    private boolean insertProducer(String pid, String name) {
        try {
            // SQL-Anweisung definieren
            String sql = "INSERT INTO hersteller VALUES (" + pid + ",'" + name + "')";
            // SQL-Befehl ausführen
            int count = dbcon.OraDBexecuteUpdate(sql);
            // Mißerfolg melden, falls Datensatz nicht eingefügt werden konnte
            if (count == 0) return false;
        }
        // Fehlerbehandlung
        catch(SQLException e) {
            error = e.toString();
            return false;
        }
        // Erfolg melden
        return true;
    }
    
Das Hinzufügen neuer Adreßdaten in die Datenbank übernimmt die Methode insertAddress(String producer_id, HttpServletRequest request). Diese besitzt zwei Übergabeparameter. Der Parameter producer_id gibt an, welchem Hersteller die neue Adresse zugeordnet werden soll. Über den Parameter request werden dann die neu einzufügenden Adreßdaten aus dem Formular ausgelesen und im String-Feld values zur weiteren Verarbeitung abgespeichert, bevor dann ein entsprechendes SQL-Statement generiert und ausgeführt wird. Der Rückgabewert dieser Methode gibt nach außen hin zu erkennen, ob die Operation erfolgreich war, oder ob ein Fehler aufgetreten ist. Nachfolgend der zugehörige Quell-Code.

    // neue Adreßdaten für einen Hersteller einfügen
    private boolean insertAddress(String producer_id, HttpServletRequest request) {

        try {
            // einzufügende Werte ermitteln
            for (int i=0; i<13; i++) {
                // Adreßdaten aus Formular abfragen
                values[i] = request.getParameter("adr" + fieldNames[i]);
                // event. NULL-Werte durch Leer-Stings ersetzen
                if (values[i] == null) values[i] = "";
            }
            // SQL-Statement generieren
            String sql = "INSERT INTO adresse VALUES (";
            for (int i=0; i<13; i++) {
                switch (i) {
                    case  0: sql += values[i] + "," + producer_id + ",";
                             break;
                    case  4:
                    case  5: sql += values[i] + ",";
                             break;
                    case 12: sql += "'" + values[i] + "')";
                             break;
                    default: sql += "'" + values[i] + "',";
                }
            }
            // SQL-Befehl ausführen
            int count = dbcon.OraDBexecuteUpdate(sql);
            // Mißerfolg melden, falls nichts eingefügt werden konnte
            if (count == 0) return false;
        }
        // Fehlerbehandlung
        catch(SQLException e) {
            error = e.toString();
            return false;
        }
        // Erfolg melden
        return true;
    }
    
Die Methode deleteData(String sql) übernimmt das Entfernen von Datensätzen aus der Datenbank. Als Parameter wird dieser Methode ein entsprechend formuliertes SQL-Statement übergeben. Sollten die angegebenen Daten nicht entfernt werden können, weil hierbei beispielsweise ein Constraint verletzt werden würde, so wird innerhalb der Methode OraDBexecuteUpdate(...) eine Exception ausgelöst und die entsprechende Fehlermeldung im catch-Block der Methode deleteData(String sql) zur Ausgabe aufbereitet. Der Rückgabewert dieser Methode gibt nach außen hin zu erkennen, ob die Operation erfolgreich war, oder ob ein Fehler aufgetreten ist. Nachfolgend der zugehörige Quell-Code.

    // Datensatz entfernen
    private boolean deleteData(String sql) {
        try {
            // Löschoperation ausführen
            int count = dbcon.OraDBexecuteUpdate(sql);
            // Mißerfolg melden, falls nichts gelöscht werden konnte
            if (count == 0) return false;
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            error = e.toString();
            return false;
        }
        // Erfolg melden
        return true;
    }
    
Als achte und letzte Methode stellt das Servlet EditProducer die Methode updateAddress(String address_id, HttpServletRequest request) zur Verfügung. Diese besitzt zwei Übergabeparameter. Der Parameter address_id bezeichnet dabei die Adreß-ID des Datensatzes, der modifiziert werden soll. Über den Parameter request werden schließlich die modifizierten Adreßdaten aus dem Formular ausgelesen und zur weiteren Verarbeitung im String-Feld values abgespeichert, bevor dann ein entsprechendes SQL-Statement generiert und ausgeführt wird. Der Rückgabewert dieser Methode gibt nach außen hin zu erkennen, ob die Operation erfolgreich war, oder ob ein Fehler aufgetreten ist. Nachfolgend der zugehörige Quell-Code.

    // Adreßdaten aktualisieren
    private boolean updateAddress(String address_id, HttpServletRequest request) {

        try {
            // einzufügende Werte ermitteln
            for (int i=1; i<13; i++) {
                // Adreßdaten aus Formular abfragen
                values[i] = request.getParameter("adr" + fieldNames[i]);
                // event. NULL-Werte durch Leer-Strings ersetzen
                if (values[i] == null) values[i] = "";
            }
            // SQL-Statement generieren
            String sql = "UPDATE adresse SET ";
            for (int i=1; i<13; i++) {
                switch (i) {
                    case  4:
                    case  5: sql += columnNames[i] + "=" + values[i] + ",";
                             break;
                    case 12: sql += columnNames[i] + "=" + "'" + values[i] + "' WHERE adid=" + address_id;
                             break;
                    default: sql += columnNames[i] + "=" + "'" + values[i] + "',";
                }
            }
            // SQL-Befehl ausführen
            int count = dbcon.OraDBexecuteUpdate(sql);
            // Mißerfolg melden, falls nichts modifiziert werden konnte
            if (count == 0) return false;
        }
        // Fehlerbehandlung
        catch(SQLException e) {
            error = e.toString();
            return false;
        }
        // Erfolg melden
        return true;
    }
    

zurück weiter