First steps tutorial using struts and eclipse (free tools) In diesem Tutorial möchte ich erste Schritte im Umgang mit dem Web Framework Apache Struts und der Entwicklungsumgebung Eclipse beschreiben. Als Beispiel - Anwendung erstellen wir eine Verwaltung von Büchern. Wir verwenden ausschließlich kostenlose Plugins wie Struts Console und JBOSS IDE. Allgemeines Autor: Sascha Wolski http://www.laliluna.de/tutorial.html – Tutorials für Struts, EJB, xdoclet und eclipse. Datum: November, 2st 2004 Development Tools Eclipse 3.x Struts console JBOSS IDE (wenn Du JBOSS benutzt) Sysdeo Plugin (wenn Du Tomcat benutzt) Source code: http://www.laliluna.de/tutorial/first-struts/first_steps_with_struts.zip Die Sourcen enthalten keine Projektdateien oder irgendwelche Libraries. Erstelle ein neues Projekt, wie im Tutorial erklärt, füge die Libraries hinzu, gleichfalls wie im Tutorial erklärt und kopiere die Sourcen in Dein neues Projekt. PDF Version des Tutorials http://www.laliluna.de/assets/tutorials/first-steps-with-struts-free-tools-de.pdf Inhaltsverzeichnis First steps tutorial using struts and eclipse........................................................................................ 1 Allgemeines........................................................................................................................................ 1 Voraussetzungen............................................................................................................................... 1 Installation der Struts Console........................................................................................................... 2 Erstellen des Web Projektes.............................................................................................................. 2 Erstellen einer Default und Willkommen Seite...................................................................................4 Global Action Forwards und Action Mappings................................................................................... 6 Anwendungsfall Buchliste.................................................................................................................. 7 Anwendungsfall Hinzufügen, Bearbeiten und Löschen von Daten.................................................. 16 Bearbeiten der Bücherübersicht.......................................................................................................22 Testen der Anwendung.................................................................................................................... 24 Voraussetzungen Wir setzen die Installation der Jboss IDE voraus, wenn Sie mit Jboss als Application Server arbeiten. Wie Sie ein Webprojekt erstellen und deployen finden Sie in dem Tutorial http://www.laliluna.de/webprojects-eclipse-jbosside-tutorial-de.html Wenn Sie Tomcat einsetzen können Sie alternativ das Programm http://www.sysdeo.com/eclipse/tomcatPlugin.html verwenden. Installation der Struts Console Laden Sie die Quelldateien von der Webseite http://www.jamesholmes.com/struts/console/ heruntern. Entpacke die Archivdatei der Struts Console und kopiere das Verzeichnis com.jamesholmes.console.struts in den Pfad eclipse\plugins Eclipse starten und fertig! Erstellen des Web Projektes Voraussetzung wie bereits oben erwähnt das Tutorial http://www.laliluna.de/webprojects-eclipse-jbosside-tutorial-de.html Erstellen Sie ein Webprojekt, so wie es dort beschrieben ist. Hinzufügen der Struts Unterstützung Wir müssen jetzt diverse XML Dateien und Libraries, in unser Projekt kopieren. Das ist am einfachsten, wenn man sich ein leeres Struts Projekt erstellt. Das haben wir für Dich gemacht. Lade das Projekt hier herunter. http://www.laliluna.de/assets/tutorials/struts-blanc-project-1.2.zip Kopiere den Inhalt der Archivdatei mit dem Explorer in den Workspace des Projektes unter ../eclipse/workspace/WebTutorial/ Aktualisiere das Projekt im Package Explorer. Rechte Maustaste auf das Projekt > Refresh. Nach der Aktualisierung sieht das Projekt wie folgt aus. Hinzufügen der Struts Libraries Die Struts Libraries müssen dem Projekt bekannt gemacht werden. Füge dazu die JAR Dateien unter den Projekteigenschaften hinzu. Rechte Maustaste auf das Projekt > Properties. Wähle die Einstellung Java Build Path im rechten Fenster und füge unter Libraries die JAR Dateien hinzu. Die JAR Dateien befinden sich im Projekt > WebRoot > WEB-INF > lib. Durch halten der SHIFT Taste können alle JAR Dateien makiert und eingefügt werden. Nach diesem Schritt sieht der Package Explorer wie folgt aus. Erstellen einer Default und Willkommen Seite Dann wollen wir mal unsere Default Seite erstellen. Dazu klicken wir mit der rechten Maustaste (ja schon wieder) auf den WebRoot Ordner und wählen Sie JSP aus. Wenn es dort nicht zu finden ist, ändern Sie unter Windows -> Customize perspective Ihre Einstellungen oder wählen Sie „Other“ aus und dann JSP. Wir legen jetzt eine neue index.jsp im Verzeichnis WebRoot an. Die Datei index.jsp befindet sich jetzt im WebRoot Verzeichnis des Projektes. Wenn wir die Datei öffnen, müssen wir im oberen Teil die sogenannten Struts Tag Libraries (Bibliotheken). Hinzufügen. Diese werden benötigt um die Struts eigenen Tags zu verwenden. In unserem Falle benötigen wir nur die Logic Tag Library. <%@page contentType="text/html" %> <%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> Folgende Zeile fügen wir unter den Include der Logic Tag Library. <logic:forward name="welcome" /> Diese Zeile veranlasst Struts nach einem Forward (Weiterleitung) mit dem Namen welcome zu suchen. Findet die Applikation dieses Forward nicht, führt dies zu einem Fehler. Im nächsten Abschnitt wird kurz erläutert was ein Action Forward ist. Erstelle eine zweite JSP Datei index.jsp im Verzeichnis /WebRoot/jsp. Ändere die JSP wie folgt. <%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html locale="true"> <head> <html:base /> <title>index.jsp</title> <meta <meta <meta <meta <meta </head> http-equiv="pragma" content="no-cache"> http-equiv="cache-control" content="no-cache"> http-equiv="expires" content="0"> http-equiv="keywords" content="keyword1,keyword2,keyword3"> http-equiv="description" content="This is my page"> <body> Welcome! <br> <html:link action="bookList">Show the booklist</html:link> </body> </html:html> Global Action Forwards und Action Mappings Was ist ein Action Forward? Wie der englische Name schon sagt ist ein Forward eine Weiterleitung. Es gibt in Struts zwei Typen von Forwards, zum Einen ein globales und ein lokales Action Forward. Das globale Action Forward kann aus jeder Action Klasse und JSP Datei aufgerufen werden. Das lokale Action Forward wiederum nur aus der zugehörigen Action Klasse. Was ist ein Action Mapping? Das Action Mapping von Struts ist das Herzstück für die Interaktion mit dem Benutzer. Es wird festgelegt welche URL auf welche Action Klasse verweist und welche JSP Dateien von dieser Action Klasse aufgerufen werden kann. Das Diagramm zeigt, wie sich der Applikationsserver beim Aufruf der index.jsp oder eines unbekannten Action Mappings verhält Erstelle im ersten Schritt das Action Mapping. Dazu öffnen wir die Konfigurationsdatei strutsconfig.xml im Verzeichnis WebRoot/WEB-INF. Jetzt wird die Struts Console geöffnet. (Passiert das nicht, bitte die struts-config.xml mit rechtem Maustaste anklicken und „Open with“ auswählen. Klicke auf Action Mappings und wähle Add. Gebe als Path /default ein und wähle bei Action Type Forward aus. Bei Forward Path tragen wir unsere Willkommen Seite /jsp/default.jsp ein. Im zweiten Schritt erstellen wir nun das Global Action Forward. Klicke auf „Global Forwards“ und wähle „Add“. Nenne es welcome und gib als Pfad /default.do (unser Action oben) an. Anwendungsfall Buchliste Eine Struts Action tut immer irgendwas und speichert das Ergebnis in einem Actionform. Die Daten des ActionForms können dann für die Anzeige in einem JSP verwendet werden. Unser Action wird Bücher aus einer Datenbank laden und in eine ActionForm speichern. Das JSP wird diese Daten dann nacher anzeigen. Erstellen einer Objekt Klasse „Book“ Erstelle im Package de.laliluna.tutorial.library eine neue Klasse Book. Die Klasse Book soll ein Buch darstellen mit den Eigenschaften Id, Autor, Titel, Verfügbarkeit. Wir legen dafür vier Variablen an. Um auf die privaten Variablen zugreifen zu können, erstellen wir für jede einen Getter und Setter. Rechte Maustaste in der Klasse, Source > Generate Getters and Setters. Wähle Select All und Insertion point Last method. Füge noch zwei Konstruktoren der Klasse hinzu, damit wir beim Initialiseren der Klassen die Eigenschaften setzen können. // Contructor public Book(){} // Contructor to initial the properties public Book(long id, String author, String title, boolean available) { this.id = id; this.author = author; this.title = title; this.available = available; } Damit ist unser Klasse Book fertig. Erstellen eines Form Beans, Action Form und JSP Erstelle eine neue Klasse, die du von ActionForm ableitest. Das ActionForm wird unsere Bücher für die Anzeige speichern. Öffne die struts-config.xml und füge mit der Struts Console ein neus Form Bean hinzu. Der Typ ist unser eben erstelltes ActionForm. Bearbeiten des Quelltextes der Action Form Klasse Öffne die Datei BookListForm.java und füge den folgenden Quelltext hinzu. public class BookListForm extends ActionForm { private Collection books; /* lalinuna.de 02.11.2004 * get the collection books */ public Collection getBooks() { return books; } /* lalinuna.de 02.11.2004 * set the collection books */ public void setBooks(Collection books) { this.books = books; } } /* lalinuna.de 02.11.2004 * reset the collection books */ public void reset(ActionMapping arg0, HttpServletRequest arg1) { books = new ArrayList(); } Wir definieren in der Action Form Klasse eine Collection books und erstellen für diese einen Getter und Setter. In der Methode reset initialiseren wir die Collection mit einem neuen ArrayList. Erstellen eines Action Mappings und einer Action Klasse Erstelle eine neue Klasse BookListAction. Diese Klasse wird die Bücher aus der Datenbank laden und in unserem BookListForm speichern. Bearbeiten des Quelltextes der Action Klasse Öffne die Klasse bookListAction und implementiere die Methode execute ab. Mit dem Aufruf mapping.findForward("showList") suchen wir ein lokales Forward mit dem Namen showList, welches wir vorher beim Action Mapping angelegt haben. /** * Method execute * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookListForm bookListForm = (BookListForm) form; /* lalinuna.de 03.11.2004 * init SimulateDB class and set some dummy data */ SimulateDB simulateDB = new SimulateDB(); bookListForm.setBooks(simulateDB.getAllBooks(request.getSession())); } return mapping.findForward("showList"); Klasse zum Bereitstellen von Testdaten hinzufügen Wir werden in diesem Tutorial keine Datenbank benutzen. Kopiere dafür bitte aus dem Quellkode (Download siehe oben) die Java Klasse simulateDB.java und füge sie in das Package de.laliluna.tutorial.library ein. Struts Konfiguration für die BookList Erstelle mit der Struts Console ein neues Actionmapping. Der path beginnt mit einem „Slash“ und der Typ entspricht dem eben erstellen Action. Klicke dannach in der Konsole auf das Action Mapping für die erweiterten Einstellungen. Erstelle noch ein Forward für das Action Mapping auf die JSP Datei mit dem Namen showList Ausgabe der Testdaten in der JSP Datei Erstelle eine JSP mit Namen bookList.jsp im Verzeichnis /jsp/ und füge folgenden Quelltext ein. <%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%> <html> <head> <title>Show book list</title> </head> <body> <table border="1"> <tbody> <%-- set the header --%> <tr> <td>Author</td> <td>Book name</td> <td>Available</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <%-- check if book exists and display message or iterate over books --%> <logic:empty name="bookListForm" property="books"> <tr> <td colspan="5">No books available</td> </tr> </logic:empty> <logic:notEmpty name="bookListForm" property="books"> <logic:iterate name="bookListForm" property="books" id="book"> <tr> <%-- print out the book informations --%> <td><bean:write name="book" property="author" / ></td> <td><bean:write name="book" property="title" / ></td> <td><html:checkbox disabled="true" name="book" property="available" /> </td> book --%> paramName="book" <%-- print out the edit and delete link for each <td><html:link action="bookEdit.do?do=editBook" paramProperty="id" paramId="id">Edit</html:link></td> <td><html:link action="bookEdit.do?do=deleteBook" paramName="book" paramProperty="id" paramId="id">Delete</html:link></td> </tr> </logic:iterate> </logic:notEmpty> <%-- end interate --%> </tbody> </table> </body> </html> Mit dem Tag <logic:iterate> loopen wir über die Collection books unseres Form Beans bookListForm. Innerhalb des <logic:iterate> Tags können wir über den Namen book auf die Eigenschaften der Book Klasse zugreifen. Der Tag <bean:write> schreib eine Eigenschaft (Autor, Titel) an die aktuelle Stelle. <html:checkbox> erstellt eine Checkbox. Es ist geschafft puhhhh, wir haben unser Form Bean mit Action Form Klasse, unser Action Mapping mit Action Klasse und unsere JSP, die uns zur Anzeige dient, angelegt. Wenn Sie möchten können Sie den ersten Teil Ihrer Anwendung bereits jetzt testen. Am Ende des Tutorials zeigen wir wie. Anwendungsfall Hinzufügen, Bearbeiten und Löschen von Daten Im nächsten Schritt wollen wir Daten hinzufügen, bearbeiten und löschen. Das Verfahren ist identisch, • Action • ActionForm • Struts Konfiguration Neues Form Bean Lege dazu ein neues Form Bean BookEditForm.java im Package de.laliluna.tutorial.library.form. Erstelle eine neue Instanz book der Klasse Book. Book book = new Book(); Generiere für die Intanz einen Getter und Setter. Und delegiere alle Methoden der Klasse Book Der Quelltext sieht wie folgt aus: public class BookEditForm extends ActionForm { Book book = new Book(); public Book getBook() { return book; } public void setBook(Book book) { this.book = book; } public boolean equals(Object arg0) { return book.equals(arg0); } public String getAuthor() { return book.getAuthor(); } public long getId() { return book.getId(); } public String getTitle() { return book.getTitle(); } public int hashCode() { return book.hashCode(); } public boolean isAvailable() { return book.isAvailable(); } public void setAuthor(String author) { book.setAuthor(author); } public void setAvailable(boolean available) { book.setAvailable(available); } public void setId(long id) { book.setId(id); } public void setTitle(String title) { } book.setTitle(title); } public String toString() { return book.toString(); } Damit ist die Klasse Book der Action Form Klasse zugewiesen und man kann später im Formular auf die Eigenschaften zugreifen. Erstellen der Action Klasse Erstelle eine neue Klasse. Einen kleinen Unterschied gibt es bei unserer neuen Action Klasse. Diese leitet sich nicht wie vorher von der Superclass org.apache.struts.Action ab, sondern in diesem Falle von der Klasse org.apache.struts.DispatchAction. Eine DispatchAction erlaubt uns unterschiedliche Methoden aufzurufen, statt nur der execute Methode. Mit einem Parameter können wir steuern, wann die create/edit/delete Methode aufgerufen wird. Quelltext der DispatchAction Klasse Öffne die Datei bookEditAction.java. Füge folgende Methoden der Klasse hinzu. /** * Method editBook * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward editBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * get id of the book from request */ long id = Long.parseLong(request.getParameter("id")); /* lalinuna.de 04.11.2004 * init SimulateDB class and get book by id */ SimulateDB simulateDB = new SimulateDB(); bookEditForm.setBook(simulateDB.loadBookById(id, request.getSession())); return mapping.findForward("showEdit"); } Die Methode editBook ruft die übergebene id aus dem request ab und liest das Buch aus der simulierten Datenbank. Das Forward showEdit verweist danach auf die JSP Datei zum Editieren. /** * Method deleteBook * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward deleteBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * get id of the book from request */ long id = Long.parseLong(request.getParameter("id")); /* lalinuna.de 04.11.2004 * init SimulateDB class and delete book by id */ SimulateDB simulateDB = new SimulateDB(); simulateDB.deleteBookById(id, request.getSession()); return mapping.findForward("showList"); } Die Methode deleteBook ruft die übergebene id aus dem request ab und löscht das Buch aus der simulierten Datenbank. Danach verweist das Forward showList auf die Bücherübersicht. /** * Method * @param * @param * @param addBook mapping form request * @param response * @return ActionForward */ public ActionForward addBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookEditForm bookEditForm = (BookEditForm) form; return mapping.findForward("showAdd"); } Die Methode addBook verweist auf die angelegte bookAdd.jsp /** * Method saveBook * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward saveBook( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BookEditForm bookEditForm = (BookEditForm) form; /* lalinuna.de 04.11.2004 * init SimulateDB class and get data by id */ SimulateDB simulateDB = new SimulateDB(); simulateDB.saveToDB(bookEditForm.getBook(), request.getSession()); return mapping.findForward("showList"); } Die letze Methode saveBook liest die Instanz book aus dem Form Bean BookEditForm und ruft eine Methode saveToDB zum Speichern des Buches auf. Danach wird auch hier auf die Bücherübersicht verwiesen. Struts Konfiguration Erstelle mit der Struts Console ein neues Form Bean. Erstelle dann ein neues Action Mapping. Unter Parameter vergeben wir einen Parameter do. Dieser wird von unserer DispatchAction Klasse benötigt. Ändere das FormBean für das Action. Richte unter Forward drei neue Forwards ein. Zum einen für die JSP Datei zum Bearbeiten. Ein Zweites für das Anlegen eines Buches und zu guter letzt ein Forward, dass uns wieder auf die Bücherübersicht leitet. Das letzte Forward weist nicht wie üblich auf eine JSP Datei, sondern direkt auf ein vorhandes Action Mapping. Erstelle im Anschluss eine neue JSP Datei bookAdd.jsp im Verzeichnis /WebRoot/jsp. Auf diese JSP verweisst unser Forward showAdd. Erstellen des Quelltextes für die JSP Dateien Öffne die Datei bookAdd.jsp und füge folgenden Quelltext ein. <%@ <%@ <%@ <%@ page language="java"%> taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <html> <head> <title>Add a book</title> </head> <body> <%-- create a html form --%> <html:form action="bookEdit"> <%-- print out the form data --%> <table border="1"> <tr> <td>Author:</td> <td><html:text property="author" /></td> </tr> <tr> <td>Title:</td> <td><html:text property="title" /></td> </tr> <tr> <td>Available:</td> <td><html:checkbox property="available" /></td> </tr> <tr> <td colspan="2"> <html:submit>Save</html:submit> </td> </tr> </table> <%-- set the parameter for the dispatch action --%> <html:hidden property="do" value="saveBook" /> </html:form> </body> </html> Der Tag <html:form> erstellt ein neues HTML Formular und weisst mit action=“bookEdit“ auf das vorher angelegte Action Mapping. Der Tag <html:text> schreibt ein Textfeld mit der Eigenschaft Autor unseres Buches. <html:hidden> erstellt ein Hidden Formular Feld mit Namen do. Wir benötigen dieses Feld um unserer DispatchAction Klasse zu sagen, welche Methode sie aufrufen soll. Öffne die Datei bookEdit.jsp. Wir können den Quelltext von der Datei bookAdd.jsp verwenden. Ändere folgende Zeilen ab. <title>Edit a book</title> Füge folgende Zeilen über <html:hidden property="do" value="saveBook" /> <%-- hidden field that contains the id of the book --%> <html:hidden property="id" /> Das wars auch schon. Bearbeiten der Bücherübersicht Öffne die Datei bookList.jsp und ändere den Quelltext wie folgt ab. <%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%> <html> <head> <title>Show book list</title> </head> <body> <table border="1"> <tbody> <%-- set the header --%> <tr> <td>Author</td> <td>Book name</td> <td>Available</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <%-- check if book exists and display message or iterate over books --%> <logic:empty name="bookListForm" property="books"> <tr> <td colspan="5">No books available</td> </tr> </logic:empty> <logic:notEmpty name="bookListForm" property="books"> <logic:iterate name="bookListForm" property="books" id="book"> <tr> <%-- print out the book informations --%> <td><bean:write name="book" property="author" /></td> <td><bean:write name="book" property="title" /></td> <td><html:checkbox disabled="true" name="book" property="available" /> </td> <%-- print out the edit and delete link for each book --%> <td><html:link action="bookEdit.do?do=editBook" paramName="book" paramProperty="id" paramId="id">Edit</html:link></td> <td><html:link action="bookEdit.do?do=deleteBook" paramName="book" paramProperty="id" paramId="id">Delete</html:link></td> </tr> </logic:iterate> </logic:notEmpty> <%-- print out the add link --%> <tr> <td colspan="5"><html:link action="bookEdit.do?do=addBook">Add a new book</html:link> </td> </tr> <%-- end interate --%> </tbody> </table> </body> </html> Damit haben wir unsere kleine Beispielanwendung beendet und wir können diese nun testen. Testen der Anwendung Starte den Jboss und Deploye das Projekt als Package Archive. (Auch das haben wir in dem Tutorial Webprojekte mit der Jboss IDE gezeigt.) Rufe jetzt im Webbrowser das Projekt aus http://localhost:8080/LibraryWeb/ Gratulation, das wars .... ;)