# Servet Datei schreiben



## hsch (13. Jan 2012)

Hi,

nur eine kleien Frage:

ich nehme POST-requests entgegen und rufe dann eine Methode auf, die Text in eine Datei schreibt.

Jetzt weiß ich aber nicht, wie das aussieht, wenn mehrere Clients einen request schicken, was ja eigentlich der "Normalfall" bei einem Webserver ist.

Kümmert sich mein Server (Tomcat,Jetty etc.) darum, dass die Methode Thread-safe ist oder muss ich die Methode extra als synchronized markieren?

Ich meien gelesen zu haben, dass nur eine Instanz eines Servlets erzeugt wird. Heißt das, die requests werden sequentielle abgearbeitet, so dass es nicht zu race condition kommen kann? Es also verhindert wird, dass zwei oder mehrere Threads gleichzeitig auf eine Datei zum schreiben zugreifen?


Danke für eure Hifle im vorraus 
Gruß
hsch


----------



## xehpuk (13. Jan 2012)

Hey,

ich arbeite mich gerade auch in das Thema ein.

Mein Verständnis: Es wird pro Servlet-Klasse nur eine Instanz erzeugt. Dessen 
	
	
	
	





```
service()
```
 wird jedoch immer von einem neuen Thread bzw. von einem aus dem Thread-Pool aufgerufen. Es greifen also theoretisch beliebig viele Threads gleichzeitig auf diese Instanz zu. Das heißt eben nicht, dass diese sequenziell abgearbeitet werden. Dafür musst du schon selbst Schritte vornehmen, also synchronisieren.


----------



## nillehammer (13. Jan 2012)

Es hängt vom Container ab, wie er die Servlets instanziiert. Man kann sich nicht darauf verlassen, dass es von jedem Servlet nur eine Instanz gibt. Es ist im Gegenteil sogar so, dass empfohlen wird, Servlets auf keinen Fall als Singleton zu implementieren. Das wiederum spricht eher dafür, dass der Container durch aus mehrere Instanzen in einem Pool verwaltet, um die Requests abzuarbeiten.

Wenn jeder Request auf seinen eigenen Dateien arbeitet (bspw. Nutzer laden Dateien hoch), dann hat man sowieso kein Problem mit gesharten Resourcen. Wenn aber alles in der selben Datei landen soll, muss man sich um die Zugriffsteuerung selbst kümmern.


----------



## hsch (13. Jan 2012)

alles klar. danke schön! Bei mir ist eben so, dass alle requests auf ein und derselben Datei schreiben. Also reicht es ja dann aus, die Methode synchronized zu machen, oder?! Ich habe nämlich irgendwo gelesen, man soll in Servlets mit "synchronized" aufpassen. So soll man z.b. die vom HttpServlet geerbten Methoden auf gar keinen fall als synchronized markieren.


Ich habe ein echt komisches Problem: es gibt zwei verschiedene Verhalten:

1. richtiges Verhalten
Client sendet Anfrage an den Server 
Client dahin programmiert, dass er die Antwort ausgibt
Server öffnet Datei, schreibt etwas hinein, schließt die Datei und sendet eine Antwort an den Client zurück
Client gibt Antwort aus

2. falsches Verhalten
Client sendet Anfrage an den Server
Client dahin programmiert, dass er die Antwort *nicht* ausgibt
Server erstellt keine Datei



Kann mir jemand sagen, wenn ich auf der Client Seite

```
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		
	String line;
	while((line = reader.readLine()) != null){
		System.out.println(line);
	}

reader.close();
```

auskommentiere, der Server keine Datei mehr erzeugt?


----------



## hsch (13. Jan 2012)

Das gleiche Verhalten habe ich auch beim Lesen einer Datei auf Serverseite. Verwende ich keinen BufferedReader so wird die Datei nicht gelesen. 

Weiß jemand rat?


----------



## nillehammer (13. Jan 2012)

> Ich habe nämlich irgendwo gelesen, man soll in Servlets mit "synchronized" aufpassen. So soll man z.b. die vom HttpServlet geerbten Methoden auf gar keinen fall als synchronized markieren.


Stimmt, das geht in die ähnliche Richtung wie Servlets nicht als Singleton. Das führt nämlich zu Performanceengpässen. Der Hintergrund ist, dass es bei Servlets eigentlich nicht nötig sein sollte, synchronized zu verwenden, da Servlets keine Instanzvariablen haben sollten, bei denen ein konkurrierender Zugriff problematisch wäre. Wenn aber Servlets auf eine externe geharte Resource zugreifen (z.B. eine gemeinsame Datei), dann sollte die Zugriffschicht sich darum kömmern, z.B. eine  von Dir Programmierte Klasse FileAccessService.



> auskommentiere, der Server keine Datei mehr erzeugt?


Hmm, ich nehme an, dass erst das Lesen von einem Inputstream der HttpUrlConnection? dazu führt, dass der Request überhaupt abgesetzt wird. Davor das ganze geraffel stellt nur die Verbindung auf Netzwerkebene her, setzt aber noch nicht den Request ab. Verifiziere das, indem du einfach einen Sysout.println("aufgerufen") an den Anfang der doGet/doPost-Methode schreibst. Wenn die Ausgabe nicht kommt, war die Erklärung richtig.


----------



## DerFeivel (13. Jan 2012)

Die Frage nach den Instanzen ist eigentlich in der Spec eindeutig unter Punkt SRV2.2 geklärt:

http://www.inf.unibz.it/~ricci/MS/Material/servlet-2_3-fcs-spec.pdf



> For a servlet not hosted in a distributed environment (the default), the servlet
> container must use only one instance per servlet declaration



Entspricht der Server der Spezifikation, so heisst das:


Solange du dein Servlet nicht als distributeable kennzeichnest, hast du pro Servlet-Mapping auf das Servlet genau eine Instanz auf die dann mehrere Threads zugreifen.

Pro Servlet-Mapping heisst:

Wenn du in deiner Web.xml ein Url-Pattern auf deine Servlet-Klasse mappst -->   eine Servlet-Instanz

Wenn du in deiner Web.xml zwei Url-Pattern auf deine Serlvet-Klasse mappst  --> zwei Servlet-Instanzen



Was willst du in die Datei schreiben? Nur einen kleinen Teil, oder abhängig vom Request?

Wenn du synchronized benutzt, sollte dir dann bewusst sein, dass du alle anderen einkommenden Request für die Zeit der synchronized-Aufrufe blockst. Je nach Dauer deiner Datei-Operationen kann das dann zu Read-Timeouts führen (und Angreifern Tür und Tor öffnen...).
Ein Thread (Request) blockt die Bearbeitung aller anderen Threads (Request) die auf die Methode zugreifen, bis er fertig ist(siehe Synchronized Methods (The Java™ Tutorials > Essential Classes > Concurrency).


Nachtrag:

Ggf. kann man auch Server-interne Logging-Mechanismen für sowas missbrauchen. Aber das hab ich dann nicht gesagt


----------

