# Exception: getOutputStream() has already been called



## k4lle (25. Jan 2008)

Ich habe folgendes Problem. Ich will eine Liste durchlaufen und diese in XLS transformieren.
Die export-Methode sieht wie folgt aus.


```
public String exportieren(){
..
		try{
			FacesContext context = FacesContext.getCurrentInstance();
			if(!context.getResponseComplete()){
				HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
				response.setContentType("application/vnd.ms-excel");
				response.setHeader("Content-disposition", "inline; filename=\"test.xls\"");
				
				OutputStream out;
				out = response.getOutputStream();
				workbook().write(out);
				out.flush();
				out.close();
				context.responseComplete();
			}
..
}
```

Jetzt kommt mein eigebtliches Problem. Meine workbook()-Methode die in den OutputStream geschrieben wird sieht wie folgt aus:

1)   

```
private HSSFWorkbook workbook(){
..
		for(ListIterator<Maschinendaten> iter = test.listIterator(); iter.hasNext();){
			//Zellen mit Daten füllen			
			row = sheet.createRow(rowIndex++);
			cell = row.createCell((short) 0);
			cell.setCellValue(iter.next().getBetriebsmittel());
		}
		
		rowIndex = 1;
		
		for(ListIterator<Maschinendaten> iter = test.listIterator(); iter.hasNext();){
			//Zellen mit Daten füllen

			row = sheet.createRow(rowIndex++);
			cell = row.createCell((short) 1);
			cell.setCellValue(iter.next().getBenennung());
		}
..
}
```

Wenn sich innerhalb der Methode diese beiden Iteratoren befinden, dann bekomme ich wunderbar in Exel eine Tabelle mit den Inhalten von getBetriebsmittel und getBenennung angezeigt. So soll es sein. Trotzdem ist das bestimmt total häßlich gemacht. Ich kann ja nicht für 20 verschiedene Werte 20 Iteratoren laufen lassen. Das muss doch besser gehen!!!

2)

```
private HSSFWorkbook workbook(){
..
		for(ListIterator<Maschinendaten> iter = test.listIterator(); iter.hasNext();){
			//Zellen mit Daten füllen			
			row = sheet.createRow(rowIndex++);
			cell = row.createCell((short) 0);
			cell.setCellValue(iter.next().getBetriebsmittel());
			cell = row.createCell((short) 1);
			cell.setCellValue(iter.next().getBenennung());
		}
..
}
```

Wenn die Methode so aussieht, dann bekomme ich folgende Exception geworfen:


```
java.lang.IllegalStateException: getOutputStream() has already been called for this response
	org.apache.catalina.connector.Response.getWriter(Response.java:604)
	org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:198)
	org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
	org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
	org.apache.jasper.runtime.JspWriterImpl.write(JspWriterImpl.java:326)
	org.apache.jasper.runtime.JspWriterImpl.write(JspWriterImpl.java:342)
	org.apache.myfaces.shared_impl.renderkit.html.HtmlResponseWriterImpl.write(HtmlResponseWriterImpl.java:591)
	org.apache.myfaces.taglib.core.ViewTag.doAfterBody(ViewTag.java:149)
	org.apache.jsp.sicherheit.maendern_jsp._jspx_meth_f_005fview_005f0(maendern_jsp.java:152)
	org.apache.jsp.sicherheit.maendern_jsp._jspService(maendern_jsp.java:110)
	org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:419)
	org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspViewHandlerImpl.java:211)
	org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41)
	org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:132)
	javax.faces.webapp.FacesServlet.service(FacesServlet.java:140)
```

somit muss der fehler in der for-schleife liegen. kann es sein, dass nach dem ersten durchlauf der iterator nicht auf das erste element zeigt? 
wäre schön, wenn ihr mir dazu was sagen könnten und mir erklären könnt was ich falsch mache. danke


----------



## maki (25. Jan 2008)

Das Problem ist imho ein anderes:
Irgendwann ruft eine JSP den getOuputStream wieder auf, dann kommt der Fehler, wahrscheinlich wenn nix transferriert wurde.

Was benutzt du?
JSP und Servlets?
Struts?
JSF?


----------



## k4lle (25. Jan 2008)

ich benutze JSF. meine exportieren-methode wird durch einen command-button aufgerufen. (action-methode).

ich habe zu der exception die geworfen wird ein paar sachen im inet gelesen. habe das aber nicht wirklich verstanden. 
wenn ich das richtig verstanden habe, dann wird der getOutputStream() durch eine JSP seite aufgerufen. jetzt rufe ich diesen aber noch mal auf und dann kommt die fehlermeldung. 
deswegen wurde gesagt, dass man die transformation in ein servlet schreiben soll, weil man da keine probleme mit dem aufruf des getOutputStream hat. Macht das Sinn?

wenn dadurch mein problem entsteht, dann frage ich mich wieso alles klappt, wenn ich mehrere iteratoren über die liste laufen lasse und die einzelnen elemente in die exel-tabelle packe?


----------



## maki (25. Jan 2008)

Machts du etwas anders, wenn die Excel Datei geschrieben wurde?

zB eine JSP anzeigen wenn nix geschrieben wurde?


----------



## k4lle (25. Jan 2008)

bisher lasse ich mir in der konsole nur die exception ausgeben falls es nicht klappt.

das entscheidende ist was ich zuerst geschrieben habe:

sieht die workbook() wie in 1) aus klappt es. so will ich es aber nicht.

sieht die workbook() wie in 2) so aus klappt es nicht. 

also würde ich denken das beim 2) mein fehler in der for-schleife liegt bzw. ich gehe da falsch mit dem iterator um.


----------



## maki (25. Jan 2008)

Dir ist klar das du in der for schleife zweimal next aufrufst und somit jedesmal 2 Elemente weitergehst?

Sowas führt normalerweise zu einer NoSuchElementException Exeption.

Wahrscheinlich versucht JSF da die Exception an den Client zu senden und stolpert da getOutputStream ja schon benutzt wurde, auch die Tatsache das eine JSP getOutputStream aufruft (siehe Exception ) deutet darauf hin.


----------



## k4lle (25. Jan 2008)

ok....  das mit dem next ist mir klar.... so soll das natürlich nicht sein..... ich will ja nicht immer ein element weiter gehen...




```
private HSSFWorkbook workbook(){
..
      for(ListIterator<Maschinendaten> iter = test.listIterator(); iter.hasNext();){
         //Zellen mit Daten füllen         
         row = sheet.createRow(rowIndex++);
         cell = row.createCell((short) 0);
         cell.setCellValue(iter.next().getBetriebsmittel());
         cell = row.createCell((short) 1);
         cell.setCellValue(iter.next().getBenennung());
         ???????
      }
..
}
```

Kann ich an der Stelle wo die ?????? stehen den iterator wieder zurück an die erste position setzten damit der nächste durchlauf wieder von vorne anfängt? 
vielleicht würde das ja zur lösung beitragen ????


----------



## maki (25. Jan 2008)

Referenzier doch das element und benutz dann nur diese Referenz, dann brauchst du auch nur einmal next() aufzurufen.

Oder Probier doch mal das hier, die for-each Schleife:

```
for (MaschinenDaten maschinenDaten : test) {
 
        row = sheet.createRow(rowIndex++);
         cell = row.createCell((short) 0);
         cell.setCellValue(maschinenDaten.getBetriebsmittel());
         cell = row.createCell((short) 1);
         cell.setCellValue(maschinenDaten.getBenennung()); 
        }
```


----------



## k4lle (25. Jan 2008)

danke....

die foreach-Schleife klappt einwandfrei. also kann ich die foreach-schleife über eine datensammlung jagen und die elmente verarbeiten?

das ich das element referenziere, mit der referenz arbeite und nur einmal next aufrufe klappt nicht. entweder das geht wirklich nicht, oder es liegt an meiner unfähigkeit ;-)


also erstmal vielen dank. ist natürlich super das du mir geholfen hast, wobei ich das natürlich lieber selber gelöst hätte.  dafür hab ich jetzt wieder was dazu gelernt. nur so kann man schließlich sein wissen und erfahrungen erweitern...


----------

