Hallo,
der letzte Newsletter ist schon etwas her. Umzug, Arbeitsstress, eine neue Anwendung, Sommerurlaub - es gibt letztlich viele Gründe dafür. Außerdem standen in dieser Phase neue Kapitel im Vordergrund. Bevor wir die Neuerungen kurz vorstellen, kommt zunächst ein kurzer Überblick über herausragende News der letzten Zeit im Java-Umfeld:
- Tomcat hat eine stabile Version der 6er-Linie heraus gegeben. Damit unterstützt nun auch Tomcat die Neuerungen der Web-Spezifikationen aus dem letzten Jahr wie JSP 2.1, JSTL 1.2, Servlet 2.5 und die Unified Expression Language. Darüber hinaus hat Tomcat gegenüber Jetty und GlassFish nachgezogen und bietet nun ebenfalls einen NIO-basierten Connector inklusive Unterstützung der Push-Technologie Comet.
Angesichts der unterschiedlichen Comet-Implementierungen in den verschiendenen Servlet-Containern bleibt zu hoffen, dass die Servlet-Spezifikation 3.0 eine breit akzeptierte Lösung für Event-basierte Servlets ermöglicht (s. dazu die News über die Spezifikation 3.0 weiter unten).
Die Downloadseite und die Dokumentation des Tomcat finden Sie unter
http://tomcat.apache.org/
Informationen zum NIO-Connector beim Tomcat 6 finden Sie hier:
http://tomcat.apache.org/tomcat-6.0-doc/config/http.html
Ein Beispiel zur Nutzung von Comet mit Tomcat gibt es unter
http://tomcat.apache.org/tomcat-6.0-doc/aio.html - Eclipse hat seinen Europa-Release veröffentlicht. "Europa" ist die gleichzeitige Veröffentlichung der Basis-IDE in der Version 3.3 zusammen mit einer Reihe von auf diese Version abgestimmten Plugins (u.a. auch dem Web Tools Project). Leider ist die Download-Seite von Eclipse das reinste Chaos. Anstatt erst die Basis-IDE und dann die Plugins über den Update Manager nachzuladen, empfiehlt es sich, das All-In-One-Bundle von der folgenden Seite zu holen:
http://europa-mirror1.eclipse.org/webtools/downloads/drops/R2.0/R-2.0-200706260303/ - JRuby ist in der Version 1.0 erschienen. JRuby ist eine vollständige Implementierung von Ruby, die auf der Java Virtual Machine läuft. SUN unterstützt dieses Projekt und hat dazu zwei maßgebliche JRuby-Entwickler eingestellt. Insgesamt wird von SUN nach und nach die Unterstützung für Scripting-Sprachen innerhalb der Java-Plattform verbessert. JRuby 1.0 ist hierbei ein wichtiger Meilenstein.
Die Projektseite finden Sie hier:
http://jruby.codehaus.org/ - SUN hat den Spezifizierungsprozess zur nächsten Servlet-Spezifikation (3.0) angestoßen. Non-blocking IO und Comet stehen auf der Liste der zu realisierenden Wünsche. Zudem ist Support für FileUploads mit assoziierten Fortschrittslistenern vorgesehen. Angesichts der Besprechung der FileUpload-Bibliothek weiter unten passt diese News bestens zu diesem Newsletter ;-)
Die offizielle Seite des Java Community Projects befindet sich auf
http://jcp.org/en/jsr/detail?id=315
Mehr zu den Non-blocking Features findet man auf der folgenden Seite:
http://blogs.webtide.com/gregw/2007/06/21/1182402120000.html - Passend zur Servlet 3.0-Spezifikation wurde auch der Spezifikations-Prozess für JavaServer Faces 2.0 gestartet. Wesentliches Ziel ist es, die Konfiguration zu vereinfachen bis hin zu einer "Zero-Configuration" Webanwendung. Darüber hinaus sollen JSF-Anwendungen GET-Request erlauben und damit endlich auch Bookmark-fähige Seiten zulassen. Ebenso soll das Lebenszyklusmodell überholt werden und Ajax-artige Events unterstützen.
Die initialen Überlegungen für die Spezifikation kann man auf der JCP-Seite finden:
http://jcp.org/en/jsr/detail?id=314 - Auf der JavaONE wurde von SUN das Projekt JavaFX vorgestellt. JavaFX ist in erster Linie eine spezielle Skript-Sprache, deren Syntax teilweise stark an JSON erinnert. Die Skriptsprache soll das Arbeiten mit SWING vereinfachen und durch seine spezielle Syntax Zusammenhänge zwischen den Komponenten einer SWING-Anwendung leichter erkennbar machen. JavaFX wird von SUN als eine Antwort auf Adobes Apollo und Microsofts Silverlight angepriesen. Das scheint - jedenfalls zum gegenwärtigen Zeitpunkt - aber doch ein wenig hochgegriffen. Dennoch lohnt es sich, das Projekt im Auge zu behalten.
Die interessanteste Seite zu JavaFX ist das Planet FX-Wiki, das unter der folgenden URL erreicht werden kann:
http://jfx.wikia.com/wiki/Main_Page - NetBeans hat die Version 5.5.1 veröffentlicht und ist für die 6er-Version derzeit beim Meilenstein 10 angekommen. 5.5.1 bringt v.a. eine bessere Unterstützung für GlassFish v2 und diverse kleinere Verbesserungen und Bugfixes gegenüber der Version 5.5 mit.
Version 6.0 hingegen ist ein großer Schritt für die IDE. Bspw. ist der Java-Editor grundlegend überarbeitet und das Profiling-Plugin in die Standard-Auslieferung integriert und um Unterstützung für die Suche nach Memory Leaks erweitert worden. Eine grundlegend neue Basis für Refactorings wurde mit der Refactoring-Engine Jackpot geschaffen. Version 6 unterstützt zudem die Entwicklung mit JRuby, und auch das Modul- und UpdateCenter wurde optimiert.
Netbeans 5.5.1 und den Meilenstein 10 von Netbeans 6.0 können Sie sich von der folgenden Seite herunterladen:
http://www.netbeans.org/index.html
Eine Übersicht der Neuerungen in NB 6.0 finden Sie unter der folgenden URL:
http://wiki.netbeans.org/wiki/view/NewAndNoteWorthy - Google hat das Ajax-Offline-Framework Google Gears in einer frühen Beta-Version veröffentlicht. Google Gears besteht aus einer Kombination eines Browser-Plugins mit JavaScript-Bibliotheken. Das Plugin installiert eine SQL-fähige Datenbank (SQLite) und macht diese mittels JavaScript zugänglich. Ergänzt wird das Ganze um einen Ressourcen-Cache, auf dem im Offline-Modus zugegriffen wird (LocalServer-API), und der WorkerPool-API zur asynchronen Verarbeitung zeitaufwändiger Aufgaben (bspw. der Synchronisation zwischen Offline- und Online-Daten).
GoogleGears unterstützt derzeit den Firefox (1.5 oder größer) auf Linux, Mac OS X und Windows und den IE (ab Version 6) auf Windows. Interessanterweise derzeit nicht den Safari (weder auf dem Mac noch unter Windows) - und das, obwohl Googles CEO im Aufsichtsrat von Apple sitzt. Aber Google Gears ist ja noch im frühen Beta-Stadium, und die Browser-Unterstützung wird sicher noch ausgebaut werden.
Sowohl das Plugin, als auch die Dokumentation zur Nutzung der Gears-APIs gibt es unter
http://gears.google.com/
Unser letzter Newsletter ist zwar schon einige Zeit her, dafür waren wir aber an anderer Stelle fleißig. Die Neuerungen im Tutorial seit dem letzten Newsletter im Überblick:
- Am VisualProxy, einem Tool zur Visualisierung des HTTP-Transfers, das im Rahmen des JSP-Tutorials entstand, hat Patrick Schweizer zwei Änderungen vorgenommen. Besonders die Möglichkeit, die alten Requests löschen zu können, erleichtert das dauerhafte Arbeiten mit diesem Tool.
- Im Kapitel "Fehler- und Ausnahmebehandlung" zeigen wir die Möglichkeiten auf, die die Servlet- und JSP-Spezifikationen zum Umgang mit Exceptions anbieten. Darüber hinaus geben wir einige allgemeiner gehaltene Tipps zum Umgang mit Exceptions in Java-Projekten.
- Um das Zusammenspiel verschiedener im Tutorial behandelter Aspekte zu verdeutlichen, haben wir eine Beispielanwendung geschrieben. In dem dazugehörigen Kapitel beschreiben wir, wie die im Architektur-Kapitel abstrakt behandelte MVC-Architektur konkret aussehen könnte, und zeigen zur Verdeutlichung Codefragmente aus der Anwendung. Einen Link zum Download der kompletten Sourcen bieten wir dort selbstverständlich auch an.
- Die Beispielanwendung macht intensiven Gebrauch von der Expression Language und der Java Standard Tag Library (JSTL), so dass wir in den Kapiteln wiederholt auf die Beispielanwendung verweisen. Das Kapitel zur Expression Language ist gleichzeitig mit dem Kapitel zur Beispielanwendung aufgespielt worden.
- Ebenfalls neu ist das Kapitel zum Session-Handling, in dem wir das Thema von der grundlegenden Idee des Session-Konzepts über die Verwendung von Cookies bzw. URL-Rewriting zur Verwaltung der Session-ID bis hin zu Sicherheitsfragen im Zusammenhang mit Sessions ausführlich behandeln. Auch dort wird wiederholt auf die Beispielanwendung verwiesen.
- Kurz vor der Fertigstellung ist das Kapitel zur Java Standard Tag Library und zur Nutzung des Appservers GlassFish als lokalen Testserver. Angefangen haben wir zudem ein Kapitel, in dem wir alle Einstellungen des Deployment Deskriptors behandeln. Mehr dazu im nächsten Newsletter.
- Schlussendlich haben wir das Seitenlayout des Tutorials erheblich überarbeitet. Die Links zu den einzelnen Abschnitten sind nun übersichtlicher und ansehnlicher, der Platz der Seite wird besser ausgenutzt (besonders beim Drucken wichtig), Code-Abschnitte ragen bei Safari nicht mehr rechts über die Seite hinaus, es wurde die Nutzung von Tabellen erheblich reduziert, und ein Ausdruck des Tutorials ist nun auch mit dem Opera möglich. Wir werden das Thema jedoch weiter verfolgen und streben an, eine vollständige W3C-Validierung zu schaffen und zugleich die Seite auch für sehbehinderte Menschen gut nutzbar zu machen.
Zudem haben wir gleich mehrere Kapitel fertiggestellt:
In diesem Newsletter schließen wir mit dem Beitrag zur Bibliothek Commons-Fileupload unsere Reihe über die Jakarta-Commons-Bibliotheken ab.
Wie immer wünschen wir viel Spaß beim Lesen des Newsletters und beim Entwickeln!
Commons FileUpload
Das besondere an HTTP-Uploads
Commons-FileUpload ist eine kleine Bibliothek, die sich wirklich ausschließlich um den Bereich von Datei-Uploads über das World Wide Web kümmert. Dadurch, dass die FileUpload-Bibliothek sich auf einen so eng eingegrenzten Bereich konzentriert, ist ihre Nutzung leicht verständlich. Insofern reichen an dieser Stelle auch ein paar Beispiele und Anmerkungen.Zunächst einmal ist festzustellen, wie ein FileUpload mittels HTTP vonstatten geht - die Besonderheiten hier sind es, die letztendlich überhaupt eine eigene Bibliothek rechtfertigen. Während bei einem normalen POST-Request die Parameter direkt als Key-Value-Paare im Body des Requests zu finden sind (s. dazu die Screenshots im "Anhang I: HTTP-Grundlagen"), werden Datei-Uploads anders behandelt. Dies betrifft sowohl den HTML-Code, als auch den Transport der Datei und der anderen zusammen mit dieser Datei übermittelten Parameter mittels HTTP als auch die Auswertung in einem Servlet oder in JSPs.
Zunächst betrachten wir die Änderungen im HTML-Code. Hier muss man im
<form>-Element der HTML-Seite das Encoding des Formulars wie im folgenden Code-Fragment gezeigt setzen: <label for="uploadFile">File</label>
<input type="file" size="50" name="uploadedFile" class="fileSelector"/>
</form>
Vergisst man im HTML-Code, die Kodierungsart mittels dem Attribute "enctype" zu setzen, so werden nicht etwa die Dateiinhalte, sondern nur der Dateiname übertragen.
Außerdem ist zu beachten, dass Dateien gemäß HTTP-Spezifikation ausschließlich per POST auf den Server geladen werden können. Sofern man ein dediziertes Upload-Servlet verwendet, empfiehlt es sich, die
doGet()-Methode wie folgt zu schreiben: throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
"GET is not allowed for uploads");
}
Damit wird jeder Versuch, eine Datei per GET hochzuladen, mit einem angemessenen Fehler beantwortet. Unabhängig von der Antwort des Servers funktioniert GET analog zu einem inkorrekt gesetzten Attribut "enctype". D.h. anstelle der Dateien werden nur die Dateinamen übertragen.
Was aber bedeutet es, das Attribut
enctype auf multipart/form-data zu setzen? Die Auswirkung davon kann am Besten anhand eines konkreten Requests betrachtet werden. Wir nutzen dazu wie im JSP-Tutorial üblich das Tool "VisualProxy", das dazu dient, die Kommunikation zwischen Browser und Server zu verdeutlichen. Schaut man sich bspw. den folgenden Screenshot an, so sieht man, dass der Request-Body in mehrere deutlich getrennte Teile aufgesplittet ist. Zu jedem Form-Element gibt es einen eigenen "Part", daher auch der Name "multipart" für das Attribut "enctype".
In den gezeigten Daten erkennt man deutlich die einzelnen Bereiche mit eigenen Headern wieder. Als erstes wurde ein Textfeld übertragen - die Hinweise auf den Content-Type und den Dateinamen fehlen entsprechend. Bei den beiden folgenden Teilen der POST-Daten handelt es sich offensichtlich um Dateien. Es gibt den Header "filename", in dem der Dateiname steht, und einen Header "Content-Type", der Informationen zum Dateitypen enthält. Deutlich erkennt man zudem den Unterschied zwischen binär übertragenen Daten und Daten aus Textdateien.
Dieser Transport-Mechanismus unterscheidet sich deutlich von dem normalen Mechanismus, wie er im JSP-Tutorial im "Anhang I: HTTP-Grundlagen" beschrieben ist. Das hat entsprechende Auswirkungen auf das Auslesen von Request-Parametern. Nutzt man normalerweise dazu die Methode
getParameter(String) des Request-Objekts (s. dazu das Kapitel "Implizite Objekte"), so funktioniert das nun nicht mehr - man bekommt als Rückgabewert null zurück, unabhängig davon, ob es ein entsprechend benanntes Formularelement gibterz oder nicht. Auf die übliche Weise kommt man bei per multipart/form-data übertragenen Fomularen weder an den Inhalt der hochgeladenen Datei noch an die sonstigen Request-Parameter heran. Genau an dieser Stelle setzt nun die Upload-Bibliothek des Jakarta Commons-Projektes an. Dependencies
Commons FileUpload ist eine kleine, sehr spezialisierte Bibliothek. Entsprechend ist Commons FileUpload nur von der Bibliothek Commons-IO abhängig.Nutzung von Commons FileUpload
Ähnlich Commons HttpClient gibt es auch bei FileUpload zwei zentrale Klassen/Interfaces:org.apache.commons.fileupload.FileItem und org.apache.commons.fileupload.FileUpload. Wir zeigen zunächst ein kleines Beispiel für die Nutzung: package org.jsptutorial.examples.servlets;
import java.io.IOException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;
public class SimpleFileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// step 1: create DiskFileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
// step2: create ServletFileUpload and pass factory to constructor
ServletFileUpload upload = new ServletFileUpload(factory);
try {
// optional but highly recommendable step:
// verify if we really have an upload
RequestContext ctx = new ServletRequestContext(request);
if (ServletFileUpload.isMultipartContent(ctx)) {
// step3: parse request
List<DiskFileItem> list = upload.parseRequest(request);
// step 4: do s.th. meaningful with each part
for (DiskFileItem fileItem : list) {
String formField = fileItem.getFieldName();
String fileName = fileItem.getName();
// ...
}
}
}
catch(FileUploadException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"fileupload failed; reason: " + e.toString());
}
// some response for the client
// ...
}
}
Wie in der Beschreibung des Aufbaus von Upload-Requests im vorigen Abschnitt gesehen, enthalten Multipart-Anfragen ihrem Namen gemäß mehrere Teile, die jeweils einen Parameter eines Formulars behandeln. Der Aufbau entspricht dem Mail-Format für Mails mit Attachments, dem sogenannten MIME-Format. Die Bereiche sind, wie im obigen Screenshot erkennbar, durch den im Header "Content-Type" angegebenen Begrenzer ("boundary") voneinander getrennt und enthalten eigene Header-Angaben, die über die normalen Request-Header hinaus ergänzende Informationen zu den jeweiligen Teilen enthalten (bei Uploads bspw. den Namen des Formular-Elements, den Dateinamen und das Datenformat).
Die einzelnen Teile eines Multipart-Requests sind für Commons FileUpload repräsentiert durch Objekte vom Typ
org.apache.commons.fileupload.FileItem. Auch normale Formular-Elemente, die mit einem Upload mitgeschickt wurden, werden als FileItems repräsentiert; der Name ist somit etwas unglücklich gewählt. Erzeugt werden FileItems mithilfe einer geeigneten
FileItemFactory. Hierbei handelt es sich ebenfalls um ein Interface aus dem Package org.apache.commons.fileupload. Diese Factory braucht das FileUpload-Objekt bevor es den Request analysiert, entweder durch Übergabe an den Konstruktor oder durch Aufruf der Methode setFileItemFactory(). Die eigentlich interessante Arbeit geschieht in den Unterklassen von
org.apache.commons.fileupload.FileUploadBase: Für Servlet-basierte Uploads ist dies org.apache.commons.fileupload.servlet.ServletFileUpload, für Portlet-basierte Uploads org.apache.commons.fileupload.portlet.PortletFileUpload. Die wichtigste Methode ist schon im obigen Beispiel zu sehen. Es ist die Methode parseRequest, der je nach Umgebung ein javax.servlet.http.HttpServletRequest oder ein javax.portlet.ActionRequest mitgegeben wird. Der Rückgabewert dieser Methode ist eine Liste von FileItem-Objekten. Bei den jeweiligen FileItems kann man sich nun über die Methode get() das Ergebnis in Form eines Byte-Arrays, mit der Methode getString() als String oder mit der Methode getInputStream() als InputStream abholen. Die Bibliothek bringt selber jeweils nur eine Implementierung der
FileItem- und FileItemFactory-Interfaces mit: DiskFileItem und DiskFileItemFactory aus dem Package org.apache.commons.fileupload.disk. Auch hier entspricht der Name nicht ganz dem, was man erwarten würde. Im Gegensatz zum Namen werden nämlich nicht alle DiskFileItems direkt auf der Platte gespeichert, sondern zunächst nur solche, die eine gegebene Größe überschreiten. Die Default-Größe, ab der Elemente auf der Platte zwischengespeichert werden, beträgt 10 Kilobyte, kann allerdings durch Aufruf der Methode setSizeThreshold(int) der DiskFileItemFactory geändert werden. Ebenso kann über die DiskFileItemFactory der Ordner für die temporären Dateien vergeben werden. Wird dieser Wert nicht gesetzt, wird die System-Property für temporäre Dateien verwendet ("java.io.tmpdir").1Die meisten Methoden in den FileUpload-Klassen sind protected, so dass neben
parseRequest nur zwei weitere Methoden für die Entwicklerin von Interesse sind. Mit der Methode isMultiPartContent(RequestContext)kann und sollte geprüft werden, ob überhaupt eine Upload-Anfrage vorliegt. Prüft man dies nicht ab und das Servlet wurde mit einem normalen Formular aufgerufen, bekommt man eine InvalidContentTypeException (eine innere Klasse von FileUpload; s. dazu den Abschnitt zu Exceptions weiter unten). Die andere öffentliche Methode aus
FileUploadBase sollte man möglichst immer nutzen. Mit setSizeMax(long) gibt man die Anzahl der maximal zulässigen Bytes pro Upload an. Man kann auch den Wert -1 für unbeschränkte Uploads angeben, was auch der Standard-Wert ist. Aber davon kann ich aus Performancegründen nur abraten (s. nächsten Abschnitt). Performance-Warnung
FileUploads blockieren Threads des ServletContainers für eine lange Zeit. Dabei ist die Anzahl der maximal zulässigen gleichzeitig bearbeitbaren Threads begrenzt. Belässt man die hochladbare Datenmenge bei dem Standardwert, d.h. man begrenzt die Datenmenge gar nicht, so können schon relativ wenige unerwartet große Upload-Streams den Server lahm legen. Einen allgemeinen Richtwert für eine zulässige Upload-Größe kann man nicht angeben. Dieser ist von den zur Verfügung stehenden Ressourcen und vor allem von der geplanten Anwendung abhängig. Fest steht aber: Man sollte eine klar definierte Grenze haben.Die Threads des Threadpools eines Servlet-Containers stehen ohne besondere Vorkehrungen allen Requests gleichermaßen zur Verfügung, unabhängig davon, ob es sich um Uploads oder Standard-Requests handelt. Da Uploads zeitintensiv sind und immer einen der Threads für verhältnismäßig lange Zeit blockieren, stehen dem Rest der Anwendung entsprechend weniger Threads zur Verfügung. Hier müssen ggf. die Einstellungen des Threadpools (bei Tomcat ist dies im Connector-Element in der Datei "server.xml" konfiguriert; bei GlassFish im "request-processing"-Element in der Datei "domain.xml") angepasst werden. Eine automatische Überwachung des Threadpools bietet sich ebenfalls an - in der Startphase einer neuen Anwendung ist eine Überwachung des Pools zur Feinjustierung der Konfiguration ohnehin unerlässlich.
Als zusätzlichen Punkt sollte man - ähnlich dem bei Commons HttpClient Gesagten - auch bei Commons FileUpload beachten, dass man außer bei Kleinst-Uploads das Ergebnis nie mit
get() als Byte-Array auslesen sollte. Stattdessen empfiehlt es sich, die Daten immer in Form eines InputStreams, den man sich mit getInputStream() holen kann, weiter zu verarbeiten. Auf diese Weise wird ein mehrfaches, unnötiges Umkopieren der Daten vermieden. Eigene FileItem- und FileItemFactory- Implementierungen
Im Abschnitt "Nutzung von Commons FileUpload" weiter oben wurde erwähnt, dass es von den InterfacesFileItemFactory und FileItem jeweils nur eine Implementierung gibt, die zusammen das Speichern der FileItems auf die Festplatte steuern, sofern die einzelnen Multipart-Teile eine gewisse Größe überschreiten. Das mag nicht immer wünschenswert sein. Denkbar wäre, dass man die eintreffenden Uploads gleich in eine Datenbank speichern oder über das Netz weiterreichen will. In solchen Fällen macht das temporäre Speichern keinen Sinn. Als eine Lösung könnte man sich Implementierungen schreiben, die die Daten nur im Speicher halten. Serhat Cinar hat in seinem Blog eine entsprechende Implementierung von InMemoryFileItem und InMemoryFileItemFactory mit vollständigem Quellcode angegeben. Hierbei ist natürlich der Speicherverbrauch deutlich größer als bei der DiskFileItem-Implementierung und eine umsichtige Handhabung dringend angeraten.
Ein anderes Beispiel ist eine Umsetzung, die ich vor kurzem vorgenommen habe, bei der eine
FileItem-Implementierung mit Listener-Unterstützung zum Tragen kam, um Ajax-basierte Fortschrittsbalken beim Fileupload anzeigen zu können. Exceptions
Bei einem FileUpload können etliche Fehlerfälle auftreten, für die die Bibliothek Commons FileUpload geeignete Exceptions mitbringt. Die im Folgenden aufgelisteten Exception-Klassen liegen alle im Packageorg.apache.commons.fileupload. | Exception | Ursache |
| FileUploadException | Basisklasse für die folgenden drei Exceptions, die aber in speziellen Fällen auch direkt geworfen wird. Kündigt allgemein Fehler bei der Requestbearbeitung an. |
| FileUploadBase.InvalidContentTypeException | Wird beim Parsen geworfen, wenn kein Multipart-Request vorliegt. |
| FileUploadBase.SizeLimitExceededException | Diese Exception teilt mit, dass die Größe des Contents das vorgegebene Maximum übersteigt. |
| FileUploadBase.UnknownSizeException | Ist bei einem Upload der Header "Content-Length" nicht gesetzt, wird diese Exception geworfen. |
| MultipartStream.IllegalBoundaryException | Weicht die Länge eines Boundary-Strings von dem definierten Boundary-String ab, ist dieser falsch geformt und es wird diese Exception geworfen. Ist abgeleitet von java.io.IOException. |
| MultipartStream.MalformedStreamException | Exception, die anzeigt, dass der Stream fehlerhaft geformt ist oder dass beim Lesen des Streams Fehler aufgetreten sind. Ist ebenfalls von java.io.IOException abgeleitet. |
Anmerkungen:
1) Beim Tomcat ist das temporäre Verzeichnis das temp-Verzeichnis unterhalb des Tomcat-Basis-Verzeichnisses. Beim Start des Tomcats werden die von Tomcat genutzten Verzeichnisvariablen ausgegeben: Das Basis-Verzeichnis, das temporäre Verzeichnis und das Tomcat-Home-Verzeichnis. Letzteres entspricht dem Installationsverzeichnis. Die von Tomcat erwarteten Umgebungsvariablen sind in der Start-Datei catalina.sh bzw. catalina.bat erklärt. (zurück)

