W niniejszym rozdziale:
Elementy strony jako obiekty
Wyświetlanie zbioru wyników
Rozdział 16.
Element Construction Set
Pakiet Element Construction Set (ECS) prezentuje całkowicie inne podejście do tworzenia zawartości niż JSP, Tea i WebMacro. ECS odchodzi daleko od tekstu HTML i traktuje HTML jako jedynie kolejny zestaw obiektów Javy. Strona WWW w ECS jest zarządzana jak obiekt, który może zawierać inne obiekty HTML (takie jak listy i tabele), które mogą zawierać jeszcze więcej obiektów HTML (takich jak elementy listy i komórki tabeli). Ten model „obiektowego tworzenia HTML” okazuje się być bardzo potężny, ale również skoncentrowany na programiście.
Stephan Nagy i Jon Stevens stworzyli ECS i udostępnili go jako Open Source jako część Java Apache Project, oczywiście w licencji Apache. Biblioteka został utworzona według produktu htmlKona firmy WebLogic, produktu, który stracił wsparcie po wykupieniu WebLogic przez BEA Systems. W niniejszym rozdziale opisywany jest ECS w wersji 1.3.3, dostępny pod adresem http://jakarta.apche.org/ecs.
Elementy strony jako obiekty
ECS zawiera klasy dla wszystkich konstrukcji HTML 4.0. Przykład 16.1 przedstawia sposób tworzenia prostej strony HTML przy pomocy ECS.
Przykład 16.1.
Strona jako zbiór obiektów
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class ECSWitaj extends HttpServlet {
public void doGet(HttpServletRequest zad, HttpServletResponse odp)
throws ServletException, IOException {
odp.setContentType("text/html");
PrintWriter wyj = odp.getWriter();
Document dok = new Document();
dok.appendTitle("Test ECS");
dok.appendBody(new Big("Witaj!"))
.appendBody(new P())
.appendBody("Aktualny czas to " + new Date());
dok.output(wyj);
}
}
Proszę zauważyć, że wszystkie znaczniki HTML zostały zastąpione obiektami. Powyższy serwlet tworzy nowy obiekt Document przedstawiający stronę WWW, która zostanie zwrócona. Następnie dodaje do strony tytuł „ --> Test ECS[Author:F&L] ” i dodaje do jej głównej części duży napis „Witaj!”, przerwę akapitową oraz wyświetla aktualny czas. Na końcu wyświetla stronę w jej PrintWriter. W ten sposób działa obiektowe generowanie HTML — pobranie obiektu Document, dodanie do niego obiektów składowych i wysłanie go do klienta.
Aby uruchomić powyższy serwlet należy zainstalować ECS przez umieszczenie pliku JAR ECS w ścieżce klas serwera (lub w katalogu WEB-INF/lib aplikacji WWW). Dla ECS 1.3.3 plik JAR nosi nazwę ecs-1.3.3.jar. Konieczne może się okazać ponowne uruchomienie serwera w celu odnalezienia nowego pliku JAR. Po zainstalowaniu ECS można wywołać serwlet w zwykły sposób, a wygeneruje on wynik podobny do poniższego:
<html><head><title>Test ECS</title></head><body><big>Witaj!</big><p>
Aktualny czas to FRI OCT 25 23:17:37 GMT 2001</body></html>
Domyślnie wszystkie dane wyświetlane przez ECS pojawiają się w jednej linii bez wcięć i powrotów karetki. Przyśpiesza to transfer podczas komunikacji z przeglądarką klienta. Aby otrzymać zawartość łatwiejszą do odczytania należy dokonać edycji pliku ecs.properties, który jest dołączony do dystrybucji oraz zmienić wartość pretty_print na true. Następuje teraz trudniejsza część: należy upewnić się, że plik ecs.properties zostanie odnaleziony w ścieżce serwera przed plikiem JAR ECS, tak aby wyedytowany plik powodował pominięcie pliku ecs.properties zawartego w pliku JAR. Plik ecs.properties jest poszukiwany jako org/apache/ecs/ecs.properties, tak więc plik nie może zostać umieszczony bezpośrednio w ścieżce klas, ale w podkatalogu org/apache/ecs katalogu wewnątrz ścieżki klas (na przykład WEB-INF/classes/org/apache/ecs/ecs.properties).
Serwlet importuje dwa pakiety ECS — org.apache.ecs zawierający podstawowe klasy ECS i org.apache.ecs.html zawierający klasy specyficzne dla HTML. (Istnieją inne pakiety odpowiedzialne za XML, WML i RTF.) Pakiet org.apache.ecs.html zawiera prawie sto klas reprezentujących wszystkie elementy HTML 4.0. Większość klas HTML nosi nazwy odpowiadające nazwom znaczników HTML — Big, Small, P, Table, TR, TD, TH, H1, H2, H3, Frame, A, Head, Body i tak dalej. Każda klasa HTML posiada metody służące do konfiguracji elementu. Na przykład klasa TD posiada metodę setBackground(String url), która ustawia tło tej komórki tabeli. Klasa Body również posiada podobną metodę służącą do ustawiania tła dla całej strony. Żaden inny element ECS nie posiada metody setBackground(), ponieważ żaden inny element nie posiada możliwości ustawienia swojego tła, co pozwala ECS na upewnienie się, że programowo utworzone elementy zawsze zawierają prawidłowo utworzony HTML.
Aby dodać elementy głównej części, serwlet wykorzystuje łączenie metod w łańcuchy, w których kilka metod jest wywoływanych na tym samym obiekcie. W ECS można dotrzeć wiele takich konstrukcji. Na przykład, w celu utworzenia tabeli:
Table tab = new Table()
.setCellPadding(0)
.setCellSpacing(0);
Puste miejsca nie mają znaczenia. Powyższy kod jest równy następującemu:
Table tab = new Table().setCellPadding(0).setCellSpacing(0);
Powyższy łańcuch jest możliwy do utworzenia, ponieważ każda metoda set i append zwraca odwołanie do obiektu, na którym została wywołana — odwołanie to jest wykorzystywane do wywołania następnej metody. Sztuczka ta często okazuje się przydatna przy korzystaniu z ECS.
Wyświetlanie zbioru wyników
Wykorzystanie ECS do pełnego tworzenia strony wypadło z łask po ulepszeniu opartych na serwletach technologii szablonów. Po prostu dynamiczne tworzenie czegoś, co w większości jest statyczną zawartością strony zajmuje zbyt wiele czasu. Jednak ECS ciągle posiada swoje miejsce. ECS sprawdza się w przypadku tych części strony, które są wyjątkowo dynamiczne, w których do określenia zawartości do utworzenia konieczna jest pełna moc Javy. Jak powiedział Jon Stevens, jeden z jego twórców, „należy wykorzystywać ECS wszędzie tam, gdzie w innym przypadku wystąpiłoby wyj.println().”
Na przykład, proszę wyobrazić sobie aplikację WWW pozwalającą klientom na wykonywanie ad hoc zapytań w bazie danych. Na przykład mógł zostać zaimplementowany system śledzenia błędów i potrzebny jest serwlet dający zaawansowanym użytkownikom możliwość wykonywania swoich własnych zapytań w bazie danych (przy pomocy połączenia z uprawnieniami tylko-do-odczytu). ECS sprawdza się w tworzeniu strony wyświetlającej wyniki z baz danych, programowo tworząc tabelę dostosowaną do danych. Przykład 16.2 przedstawia prosty element przeglądający ResultSet. Przypomina on klasę HtmlSQLWynik przedstawioną w rozdziale 9, „Łączność z bazą danych”, która wykorzystywała wyj.println(). Zastosowanie ECS zamiast wyj.println() pozwala na uproszczenie i większe możliwości dostosowania kodu.
Przykład 16.1.
Ulepszona tabela ZbiorWynik
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class ProstaTabelaResultSet extends Table {
public ProstaTabelaResultSet(ResultSet rs) throws SQLException {
setBorder(1);
ResultSetMetaData rsmd = rs.getMetaData();
int colCount = rsmd.getColumnCount();
TR rzad = new TR();
for (int i = 1; i <= colCount; i++) {
addElement(new TH().addElement(rsmd.getColumnName(i)));
}
addElement(rzad);
while (rs.next()) {
rzad = new TR();
for (int i = 1; i <= colCount; i++) {
addElement(new TD().addElement(rs.getString(i)));
}
addElement(rzad);
}
}
}
Powyższa kasa jest rozszerzeniem org.apache.ecs.html.Table, w związku z tym reprezentuje ona element HTML <TABLE>. Wykonuje ona całą swoją pracę w konstruktorze, odczytując ResultSet i jego ResultSetMetaData w celu wygenerowania prostej tablicy wyników. Konstruktor po pierwsze wywołuje setBorder(1) w celu ustawienia atrybutu obramowania tabeli. Następnie tworzy wiersz (TR) wypełniony elementami nagłówka tabeli (TH), z których każdy wyświetla nazwę kolumny odczytaną z metadanych. Ostatecznie konstruktor wykonuje pętlę nad zbiorem wyników i tworzy wiersz dla każdego wpisu, wypełniając wiersz elementami danych tabeli (TD) zawierającymi prostą reprezentację String zbioru wyników.
Klasa ProstaTabelaResultSet może zostać bezpośrednio wykorzystana przez serwlet przy pomocy fragmentu kodu przedstawionego w przykładzie 16.3.
Przykład 16.3.
Wykorzystanie ProstaTabelaResultSet
Statement wyraz = lacz.createStatement();
boolean gotResultSet = wyraz.execute(sql); // SQL od użytkownika
if (!gotResultSet) {
wyj.println(wyraz.getUpdateCount() + "wierszy uaktualnionych.");
}
else {
wyj.println(new ProstaTabelaResultSet(wyraz.getResultSet()));
}
Powyższy kod tworzy tabelę podobną do przedstawionej na rysunku 16.1.
Rysunek 16.1. Surowy widok wyników |
|
Powyższa klasa może zostać wykorzystana w połączeniu z technologiami szablonów. Nie istnieje powód, dla którego szablon musiałby tworzyć całą zawartość HTML samodzielnie; jeżeli pewna część strony potrzebuje mocy ECS szablon może dołączyć dane wyświetlane przez element ECS do strony w odpowiednim miejscu.
Co się stanie, jeżeli tekst zwracany przez ResultSet będzie zawierał znaki, które HTML traktuje jako specjalne, jak <, > i &? Domyślnie są one dołączane bezpośrednio i potencjalnie mogą zniszczyć strukturę HTML. Aby rozwiązać ten problem, ECS zawiera klasę org.apache.ecs.filter.CharacterFilter, która dokonuje konwersji znaków specjalnych HTML na odpowiadające im encje znakowe. Każdy element używa tego filtru jako filtru domyślnego, ale z drugiej strony domyślnie całe filtrowanie jest wyłączone w celu przyśpieszenia działania. Filtrowanie można włączyć dla danego elementu poprzez wywołanie setFilterState(true) lub dla całego systemu poprzez edycję ecs.properties i ustawienie wartości filter_state i filter_attribute_state na true. W takim przypadku znaki specjalne w całym wyświetlanym tekście zostaną automatycznie przekonwertowane na encje znakowe.
Dostosowywanie wyświetlania
ECS wykorzystuje obiektową naturę Javy w celu stworzenia modelu wyświetlania danych o wysokim stopniu dostosowalności. Przy pomocy niewielkiej ilości kodu Javy możliwe jest utworzenie na klasie ProstaTabelaResultSet nie uproszczonej w takim stopniu tabeli TabelaResultSet. Ta nowa klasa tabeli będzie przyjmować tablicę obiektów TabelaDostosuj w celu kontrolowania zawartości dodanej do tablicy. Przykład 16.4 przedstawia interfejs TabelaDostosuj.
Przykład 16.4.
Klasa TabelaDostosuj
import java.sql.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public interface TabelaDostosuj {
public boolean przyjmij(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException;
public Element wyswietl(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException;
}
Dla mechanizmów dostosowujących, implementujących powyższy interfejs metoda accept() powinna zwracać true, jeżeli mechanizm posiada cel w obsłudze aktualnej komórki tabeli, a false, jeżeli nie. Metoda przyjmij() posiada dostęp do typu kolumny, nazwy typu kolumny, nazwy kolumny, obiektu ResultSet i indeksu kolumny w celu wspomożenia jej decyzji. Metoda wyswietl() zostaje wywołana, jeżeli przyjmij() zwróci true. Tworzy ona i zwraca Element zawierający dane komórki tabeli, które mają zostać dodane do tabeli. Wszystkie elementy HTML wykorzystują interfejs Element, tak więc poprzez zwracanie Element metoda wyswietl() ma możliwość zwracania dowolnego typu elementu.
Możliwe jest utworzenie mechanizmów dostosowujących, służących do wyświetlania wartości null, dat i liczb, jak przedstawiono w przykładach 16.5, 16.6 i 16.7. Tworzenie obiektów elementów HTML zamiast łańcuchów pozwala na uproszczenie i łatwiejsze rozszerzanie kodu. Możliwe jest także programowe ograniczenie rodzaju wyświetlanych elementów.
Przykład 16.5.
Mechanizm dostosowujący wartości null
import java.sql.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class NullDostosuj implements TabelaDostosuj {
public boolean przyjmij(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
rs.getObject(indeks);
return rs.wasNull();
}
public Element wyswietl(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
// Wyświetlenie „niedostepne” dla wpisów null
return new StringElement("niedostepne");
}
}
Przykład 16.6.
Mechanizm dostosowujący wartości dat
import java.sql.*;
import java.text.*;
import java.util.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class DataDostosuj implements TabelaDostosuj {
DateFormat fmt;
public DataDostosuj(Locale lok) {
fmt = DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT, lok);
}
public boolean przyjmij(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
return (kolumnaTyp == Types.DATE || kolumnaTyp == Types.TIMESTAMP);
}
public Element wyswietl(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
// Wyświetlenie skróconej daty i godziny przy pomocy podanej lokalizacji
return new StringElement(fmt.format(rs.getDate(indeks)));
}
}
Przykład 16.7.
Mechanizm dostosowujący wartości liczbowe
import java.sql.*;
import java.text.*;
import java.util.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class LiczbaDostosuj implements TabelaDostosuj {
NumberFormat fmt;
public LiczbaDostosuj(Locale lok) {
fmt = NumberFormat.getNumberInstance(lok);
}
public boolean przyjmij(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
return (kolumnaTyp == Types.TINYINT ||
kolumnaTyp == Types.SMALLINT ||
kolumnaTyp == Types.INTEGER ||
kolumnaTyp == Types.BIGINT ||
kolumnaTyp == Types.REAL ||
kolumnaTyp == Types.FLOAT ||
kolumnaTyp == Types.DOUBLE);
}
public Element wyswietl(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
// Wyświetlenie liczby przy pomocy podanej lokalizacji
if (kolumnaTyp == Types.TINYINT ||
kolumnaTyp == Types.SMALLINT ||
kolumnaTyp == Types.INTEGER ||
kolumnaTyp == Types.BIGINT) {
return new StringElement(fmt.format(rs.getLong(indeks)));
}
else {
return new StringElement(fmt.format(rs.getDouble(indeks)));
}
}
}
Możliwe jest również utworzenie bardziej zaawansowanego mechanizmu dostosowującego, zmieniającego wszystkie identyfikatory błędów w tabeli na hiperłącza do serwletu „widok błędów”. Następnie niezależnie od zapytania przekazanego przez użytkownika, identyfikatory błędów będą tworzone jako hiperłącza. Przykład 16.8 przedstawia ten mechanizm.
Przykład 16.8.
Mechanizm dostosowujący identyfikatory błędów
import java.sql.*;
import java.text.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class BladIdDostosuj implements TabelaDostosuj {
String bladWidokSerwlet;
public BladIdDostosuj(String bladWidokSerwlet) {
this. bladWidokSerwlet = bladWidokSerwlet;
}
public boolean przyjmij(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
return ((kolumnaTyp == Types.CHAR ||
kolumnaTyp == Types.VARCHAR ||
kolumnaTyp == Types.LONGVARCHAR) &&
"idbledu".equalsIgnoreCase(kolumnaNazwa));
}
public Element wyswietl(int kolumnaTyp, String kolumnaTypNazwa,
String kolumnaNazwa, ResultSet rs, int indeks)
throws SQLException {
// Utworzenie łącza do serwletu wyświetlającego dany błąd
String idbledu = rs.getString(indeks);
return new A(bladWidokSerwlet + "?idbledu=" + idbledu, idbledu);
}
}
Klasa TabelaResultSet przyjmuje w swoim konstruktorze tablicę elementów TabelaDostosuj. Dla każdej komórki mechanizmy dostosowujące umieszczone w tablicy mają możliwość kontroli tworzenia każdej komórki tabeli. Mechanizmy będą wywoływane w porządku, w jakim umieszczone są w tablicy, a zwycięża pierwszy mechanizm przyjmujący komórkę tabeli. Kod klasy TabelaResultSet jest przedstawiony w przykładzie 16.9.
Przykład 16.9.
Dostosowywana tabela ResultSet
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
public class TabelaResultSet extends Table {
public TabelaResultSet (ResultSet rs) throws SQLException {
this(rs, null);
}
public TabelaResultSet(ResultSet rs, TabelaDostosuj[] dostosuj)
throws SQLException {
setBorder(1);
if (dostosuj == null) {
dostosuj = new TabelaDostosuj[0];
}
ResultSetMetaData rsmd = rs.getMetaData();
int iloscKol = rsmd.getColumnCount();
TR rzad = new TR();
for (int i = 1; i <= iloscKol; i++) {
addElement(new TH().addElement(rsmd.getColumnName(i)));
}
addElement(rzad);
while (rs.next()) {
rzad = new TR();
for (int i = 1; i <= iloscKol; i++) {
TD td = new TD();
int kolumnaTyp = rsmd.getColumnType(i);
String kolumnaTypNazwa = rsmd.getColumnTypeName(i);
String kolumnaNazwa = rsmd.getColumnName(i);
// Danie każdemu mechanizmowi szansy kontrolowania sposobu wyświetlania
boolean dostosowany = false;
for (int c = 0; c < dostosuj.length; c++) {
TabelaDostosuj dost = dostosuj[c];
if (dost.przyjmij(kolumnaTyp, kolumnaTypNazwa,
kolumnaNazwa, rs, i)) {
td.addElement(dost.wyswietl(kolumnaTyp, kolumnaTypNazwa,
kolumnaNazwa, rs, i));
dostosowany = true;
break;
}
}
// Jeżeli brak właściwych mechanizmów, wyświetlenie wartości jako String
if (!dostosowany) {
td.addElement(rs.getString(i));
}
addElement(td);
}
addElement(rzad);
}
}
}
Zewnętrzna pętla while dokonuje iteracji na wierszach tabeli, podczas gdy zewnętrzna pętla for dokonuje iteracji na kolumnach tabeli, a wewnętrzna pętla for zarządza logiką nowego mechanizmu dostosowującego. Pierwszy mechanizm, który „przyjmie” komórkę obsługuje sposób jej wyświetlania. Jeżeli komórki nie przyjmie żaden mechanizm, tabela wyświetla prostą wartość String. Serwlet wywołujący TabelaResultSet jest przedstawiony w przykładzie 16.10.
Przykład 16.10.
Serwlet pracujący z TabelaResultSet
import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
import com.oreilly.servlet.*;
public class SerwletResultSet extends HttpServlet {
public void doPost(HttpServletRequest zad, HttpServletResponse odp)
throws ServletException, IOException {
odp.setContentType("text/html");
PrintWriter wyj = odp.getWriter();
String url = zad.getParameter("url");
String driver = zad.getParameter("driver");
String sql = zad.getParameter("sql");
// Szybkie sprawdzenie, czy url/driver/sql istnieje
ParameterParser analiza = new ParameterParser(zad);
String[] wymagany = { "url", "driver", "sql" };
String[] brakujacy = analiza.getMissingParameters(wymagany);
if (brakujacy != null && brakujacy.length > 0) {
odp.sendError(odp.SC_BAD_REQUEST,
"Podane muszą być łańcuchyURL, Driver i SQL ");
return;
}
String param1 = zad.getParameter("param1");
String param2 = zad.getParameter("param2");
String param3 = zad.getParameter("param3");
String param4 = zad.getParameter("param4");
String param5 = zad.getParameter("param5");
String param6 = zad.getParameter("param6");
String wart1 = zad.getParameter("wart1");
String wart2 = zad.getParameter("wart2");
String wart3 = zad.getParameter("wart3");
String wart4 = zad.getParameter("wart4");
String wart5 = zad.getParameter("wart5");
String wart6 = zad.getParameter("wart6");
Properties wlasc = new Properties();
if (param1 != null && wart1 != null) { wlasc.put(param1, wart1); }
if (param2 != null && wart2 != null) { wlasc.put(param2, wart2); }
if (param3 != null && wart3 != null) { wlasc.put(param3, wart3); }
if (param4 != null && wart4 != null) { wlasc.put(param4, wart4); }
if (param5 != null && wart5 != null) { wlasc.put(param5, wart5); }
if (param6 != null && wart6 != null) { wlasc.put(param6, wart6); }
Connection lacz = null;
try {
Class.forName(driver);
lacz = DriverManager.getConnection(url, wlasc);
Statement wyraz = lacz.createStatement();
boolean gotResultSet = wyraz.execute(sql);
if (!gotResultSet) {
wyj.println(wyraz.getUpdateCount() + " rzędów uaktualniono.");
}
else {
TabelaDostosuj[] dostosuj = {
new NullDostosuj(),
new DataDostosuj(zad.getLocale()),
new BladIdDostosuj(zad.getContextPath() + "/servlet/BladWidok"),
new LIczbaDostosuj(zad.getLocale()),
};
wyj.println(new ResultSetTable(wyraz.getResultSet(), dostosuj));
}
}
catch (Exception w) {
throw new ServletException(w);
}
}
}
Rysunek 16.2 przedstawia przykładowy wynik uruchomienia powyższego kodu. Proszę zauważyć, że teraz identyfikator błędu jest hiperłączem, data jest ładnie sformatowana, a opis null wyświetla „niedostepne”.
Rysunek 16.2. Dostosowany widok zbioru wyników ResultSet (data europejska) |
|
Przykład 16.11 przedstawia prosty fronton HTML dla serwletu.
Przykład 16.11.
Prosty fronton HTML dla SerwletResultSet
<HTML><HEAD><TITLE>Zapytanie SQL</TITLE></HEAD><BODY>
<P>
Niniejsza aplikacja wykonuje zapytanie SQL lub uaktualnia dowolną bazę danych
znajdującą się w sieci.
</P>
<FORM METHOD="POST" ACTION="servlet/SerlwetResultSet">
<TABLE WIDTH="75%" BORDER="1">
<TR>
<TD WIDTH="35%">URL bazy danych:</TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="url" SIZE="60"></TD>
</TR>
<TR>
<TD WIDTH="35%">Sterownik bazy danych:</TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="driver" SIZE="60"></TD>
</TR>
<TR>
<TD COLSPAN="2"><P ALIGN=CENTER> -- Właściwości bazy danych -- </p></TD>
</TR>
<TR>
<TD WIDTH="35%"><INPUT TYPE=TEXT NAME="wlasc1" VALUE="Nazwa użytkownika"></TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="wart1"></TD>
</TR>
<TR>
<TD WIDTH="35%"><INPUT TYPE=TEXT NAME="wlassc2" VALUE="password"></TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="wart2"></TD>
</TR>
<TR>
<TD WIDTH="35%"><INPUT TYPE=TEXT NAME="walasc3" VALUE="cacherows"></TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="wart3"></TD>
</TR>
<TR>
<TD WIDTH="35%"><INPUT TYPE=TEXT NAME="wlasc4"></TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="wart4"></TD>
</TR>
<TR>
<TD WIDTH="35%"><INPUT TYPE=TEXT NAME="wlasc5"></TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="wart5"></TD>
</TR>
<TR>
<TD WIDTH="35%"><INPUT TYPE=TEXT NAME="wlasc6"></TD>
<TD WIDTH="65%"><INPUT TYPE=TEXT NAME="wart6"></TD>
</TR>
</TABLE>
<P>
<TEXTAREA NAME="sql" COLS="80" ROWS="5"></TEXTAREA>
<BR>
<INPUT TYPE=SUBMIT VALUE="Wyślij SQL">
</P>
</FORM>
Powyższa demonstracja ECS jedynie dotknęła możliwości ECS. Przy dostępności całej mocy Javy można tworzyć do własnej dyspozycji strony lub części stron, które zostały w idealny sposób dostosowane do danych oraz, przy pomocy obiektowej natury ECS można ułatwić sobie pracę przy pomocy dziedziczenia, poliformizmu i silnego sprawdzania typów.
Osoby zainteresowane programowym tworzeniem XML przy pomocy Javy powinny się raczej skupić na wykorzystaniu JDOM (http://jdom.org), ponieważ JDOM jest lepiej zintegrowany z technologiami XML.
2 Część I ♦ Podstawy obsługi systemu WhizBang (Nagłówek strony)
2 H:\Książki\!Wit\Java Servlet Programming\5 do merytorycznej\r16-05.doc
Błąd w książce