# Jsp die mehrere Servlets aufruft erzeugt Fehler



## tec1 (17. Nov 2005)

Hallo Leute,

ich habe eine Strutsanwendung, welche in einer jsp mehrere Bilder darstellt. Diese Bilder(jfreecharts) werden dynamisch durch Servlets erzeugt. Soweit funktioniert alles sehr gut. 

Das Problem ist, dass die Erzeugung der Servlet-Bilder mehrere Sekunden dauern kann. Wenn der Benutzer jetzt mittendrin, in der Erzeugung der Bilder, den "zurück-button" des Browsers klickt. Kommt es manchmal zur Fehlermeldung "Cannot forward after response has been committed", wenn der benutzer dann eine andere Action mittels Link ausführt.

Wie kann ich so etwas verhindern? Bilder kann ich ja nur über Servlets erzeugen.

Gruß


----------



## Robt (17. Nov 2005)

Ich raff nicht 100%ig wie du dein Programm aufgebaut hast, aber ich hätte vielleicht eine Idee:

Während des ersten Klicks wird ja schon etwas verarbeitet und ggf auch Variablen verändert, die durch den "züruck-Button" nicht zurückgeschrieben werden. Klickst du nun zum zweiten Mal, sind die Ausgangsbedingungen nicht mehr hergestellt und er kann die neue Anforderung eventuell nicht mehr richtig bearbeiten. 
So einen ähnlichen Fehler hatte ich mal, vielleicht liegt es ja daran.....falls es nicht die Lösung sein sollte, bin ich an der richtigen auch interessiert.

Gruß Robt


----------



## tec1 (17. Nov 2005)

Ich habe eine action welche auf eine jsp forwarded.
In dieser jsp is folgender code:

```
<c:forEach begin="1" end="${fn:length(chartForm.chartList)}" var="num">
      <html:img page="/chartServlet?idx=${num}"/>

      <p style="padding-bottom: 10px;"></p>
    </c:forEach>
```

Wenn nun *mitten im Aufrufen eines Servlets in der for-schleife* der Zurückbutton gedrückt wird oder im Navigationsmenü der Anwendung ein anderer action-link geklickt wird kommt es zu der Meldung.
Mein Problem ist, dass ich nicht weiss wie ich das verhindern kann.


----------



## Bleiglanz (17. Nov 2005)

die Servlet ham damit nix zu tun

client schickt anfrage

server schickt html

browser sucht sich die img-tags und holt sich die bilder

dein problem dürfte woanders liegen: funktioniert der zurückbutton noch richtig? und wie machst du die forwards??


----------



## tec1 (17. Nov 2005)

Wie sollte denn der Zurück-button nicht richtig funktionieren?
Ich bin mir sicher, dass es im Servlet zum Fehler kommt, da es auch mehrere IO-Exceptions gibt, welche ich aber mit try catch abgefangen habe.


----------



## tec1 (17. Nov 2005)

Hier mal das Servlet welches in der jsp mehrmals aufgerufen wird. Vielleicht hat ja jemand eine Idee.


```
package de.tec.charts;



import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;

public class ChartServlet extends HttpServlet{
    private static Log log = LogFactory.getLog(ChartServlet.class.getName());
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response){
        try {
            doPost(request, response);
        } 
        catch (ServletException e) {
            if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
            return;
        }
        catch (IOException e) {
            if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
            return;
        }
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
	if (null==request.getSession().getAttribute("chartForm") || null == request.getParameter("idx"))
	    return;
	
	ChartForm form = (ChartForm) request.getSession().getAttribute("chartForm");
	
	// --- servlet parameter 'idx' ---
	int idx = Integer.parseInt((String) request.getParameter("idx"));
	idx--;
	if (log.isDebugEnabled()) log.debug("idx="+idx);
	JFreeChart chart = form.getChartList().get(idx);
	
	OutputStream out=null;
	try{
	    out = response.getOutputStream();
	} catch (IOException e){
	    // --- leave this method in case of a user wich click the back button ---
	    if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
	    out.close();
	    return;
	}
	
	try{
	    response.setContentType("image/png");
	    
	    if(null!=cashflowChart)
	    {  
		// --- chart picture as png ..., ..., width, height ---
		try{
		    ChartUtilities.writeChartAsPNG(out, chart, 1100, 700);
		} catch (IOException e){
		    // --- leave this method in case of a user wich click the back button ---
		    if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
		    return;
		}
	    }
	}
	finally{
	    try{
		out.close();
	    } catch (IOException e){
		// --- leave this method in case of a user wich click the back button ---
		if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
		return;
	    }
	}
	
    }

}
```


----------



## Bleiglanz (17. Nov 2005)

das wird nicht in der jsp aufgerufen sondern vom browser...

schreib mal einfach return in die erste Zeile, so dass im Browser kleine rote Kreuzchen kommen: hast du dann das gleiche Problem?

wieviele Bilder sinds denn eigentlich?

und: du darfst auf keinen Fall eine ServletException catchen! deinem doGet feht die richtige throws Klausel!!

und keine returns in catch-Klauseln...


----------



## tec1 (17. Nov 2005)

Wenn ich in der ersten Zeile eine return schreibe, dann werden die servlets so schnell geladen, dass ich es nicht mehr schafffe mittendrin den "Zurück-button" zu klicken.

Ich habe ca. 12 Bilder 1100 * 700 groß.

Mein Code sieht jetzt folgendermaßen aus. Der Fehler tritt weiterhin auf.


```
public class ChartServlet extends HttpServlet{
    private static Log log = LogFactory.getLog(ChartServlet.class.getName());
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
	doPost(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	if (null==request.getSession().getAttribute("chartForm") || null == request.getParameter("idx"))
	    return;
	
	ChartForm form = (ChartForm) request.getSession().getAttribute("chartForm");
	
	// --- servlet parameter 'idx' ---
	int idx = Integer.parseInt((String) request.getParameter("idx"));
	idx--;
	if (log.isDebugEnabled()) log.debug("idx="+idx);
	JFreeChart chart = form.getChartList().get(idx);
	
	OutputStream out=null;
	try{
	    out = response.getOutputStream();
	} catch (IOException e){
	    // --- leave this method in case of a user wich click the back button ---
	    if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
	}
	
	try{
	    response.setContentType("image/png");
	    
	    if(null!=chart)
	    {  
		// --- chart picture as png ..., ..., width, height ---
		try{
		    ChartUtilities.writeChartAsPNG(out, chart, 1100, 700);
		} catch (IOException e){
		    if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
		}
	    }
	}
	finally{
	    try{
		out.close();
	    } catch (IOException e){
		if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
	    }
	}
	
    }

}
```


----------



## Bleiglanz (17. Nov 2005)

kannst du mal den fehler genauer beschreiben

du rufst die Seite mit den Bildern auf

wenn du während des Ladens den Zurückbutton wählst kriegst du die Seite vorher

die stimmt soweit? oder??

dann willst du wieder eine Aktion machen: dann kommt der Fehler

und das ganze passiert NUR, wenn du während des Ladens der Bilder auf den zurückbutton klickts? wenn die vollständig geladen werden, dann ist alles OK??


----------



## tec1 (17. Nov 2005)

Jupp, genau so ist der Verlauf. Die Seite auf die ich zurückk gehe ist korekt, bei der nächsten Aktion (z.B. klick auf einen struts link, welcher eine action aufruft) kommt der Fehler.

Gruß


----------



## tec1 (18. Nov 2005)

Ich habe das jetzt so gelöst, dass ich die Erzeugung der Charts in einer anderen Klasse erledige und im Servlet dann nur noch ein byte array mit einem fertigen Bild in den ServletOutputStream packe. Das geht so schnell, dass der Benutzer keine Zeit mehr hat den Zurückbutton zu klicken. Es sollte aber trotzdem kein Fehler auftreten.


```
public class ChartServlet extends HttpServlet{
    private static Log log = LogFactory.getLog(ChartServlet.class.getName());
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
	doPost(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	if (null==request.getSession().getAttribute("chartForm") || null == request.getParameter("idx"))
	    return;
	
	ChartForm form = (ChartForm) request.getSession().getAttribute("chartForm");
	
	// --- servlet parameter 'idx' ---
	int idx = Integer.parseInt((String) request.getParameter("idx"));
	idx--;
	if (log.isDebugEnabled()) log.debug("idx="+idx);
	
	OutputStream out=null;
	try{
	    out = response.getOutputStream();
	    
	} catch (IOException e){
	    // --- leave this method in case of a user wich click the back button ---
	    if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
	}
	
	try{
	    response.setContentType("image/png");
	    
	    if(null!=form.getChartPicList().get(idx))
	    {
		byte[] aChartPic = form.getChartPicList().get(idx);
		// --- chart picture as png from a bytearray ---
		out.write(aChartPic, 0, form.getChartPicList().get(idx).length);
	    }
	}
	finally{
	    try{
		out.flush();
		out.close();
	    } catch (IOException e){
		if (log.isErrorEnabled()) log.error(e.getLocalizedMessage());
	    }
	}
	
    }

}
```


----------

