# JSP - Veständnisproblem mit Beans



## shadow (9. Mai 2007)

Hallo!

Ich habe eine Frage, die einfach zu verstehen, jedoch etwas kompliziert zu erklären ist. Deshalb versuche ich erst einmal einfach anzufangen:

Ich verwende kein Web-Framework, sondern arbeite nur mit JSP und Servlets.
Es geht um 2 JSP-Seiten: "articleList.jsp" und "article.jsp".
Den Controller der Anwendung habe ich mit einem Servlet realisiert. Dieses ist mit "do" auf die entsprechende Klasse gemapt.

Dieses Beispiel ist ohne Datenbank programmiert.


Hier ist (stark vereinfacht) die articleList.jsp:


```
<jsp:useBean id="articleList" scope="session" class="de.xxx.ArticleList" />
                                                                                           
<c:forEach items="${articleList.articles}" var="article" varStatus="forEachStatus">
   <c:out value="${article.name}" />
   <c:url var="url" value="do">
      <c:param name="action" value="showArticle" />
      <c:param name="idx" value="${forEachStatus.index}" />
   </c:url>
   [url="${url}"]Show[/url]
   

</c:forEach>
```

Hier ist ausschnittsweise der Controller:


```
// retrieve action
String action = request.getParameter("action");

if (action.equals("showArticle")) {
   ArticleList articleList = (ArticleList)session.getAttribute("articleList");
   int idx = Integer.parseInt(request.getParameter("idx"));
   Article article = (Article)articleList.getArticles().get(idx);
   session.setAttribute("article", article);
   nextPage = "article.jsp";
}
```


Dann die article.jsp:


```
<jsp:useBean id="article" scope="session" class="de.xxx.Article" />

<form action="do" method="post">

   Name: <input name="name" type="text" value="${article.name}" ></td> 

   
   <input type="hidden" name="action" value="submitArticle">
   <input type="submit">

</form>
```

Und hier wieder das benötigte Stück Controller:


```
// retrieve action
String action = request.getParameter("action");

if (action.equals("submitArticle")) {

   ....

}
```


Ich hoffe, bis hierhin ist alles soweit klar.

Erste Frage: Kann man das so machen, oder anders: ist es guter Stil?

Vorerst Danke!


P.S.: die eigentliche Frage fehlt noch...  :roll:


----------



## SlaterB (9. Mai 2007)

na soviel ist das ja nicht, da kann man dann auch nicht viel falsch machen 

------

ich bin grad bisschen aus dem Thema raus, aber mich verwirrt JSTL + jsp:useBean

wenn du schon das höhere JSTL benutzt, reicht dann nicht einfach
${session.article} statt jsp:useBean...?

na ist vielleicht nur in Struts so richtig praktikabel, wo ich das kennengelernt hatte


----------



## shadow (9. Mai 2007)

das stimmt, wahrscheinlich reicht wirklich ein ${session.article} ... das mit dem <jsp:useBean...> hab ich mir irgendwie so angewöhnt...
ok, dann wäre noch eine frage gleich: wozu benötigt man dann eigentlich <jsp:useBean...> ?


Meine eigentliche Frage ist zum Thema der Validierung von "Article":
Im Controller möchte ich beispielsweise prüfen, ob in "article.jsp" der Name des Artikels gefüllt ist, er darf nämlich nicht leer sein.


----------



## SlaterB (10. Mai 2007)

> ok, dann wäre noch eine frage gleich: wozu benötigt man dann eigentlich <jsp:useBean...> ? 

na mindestens, um ${articleList} schreiben zu können, damit das Objekt da ist,
selbst wenn du  ${session.articleList} nähmest (nehmen würdest  )
würde ${articleList} nicht gehen (solange du keine lokale Variable definierst), 
sondern bei jedem Zugriff ${session.articleList},
was auch nicht ganz zu verachten ist, da der Scope leichter zu erkennen ist

evtl. legt das useBean auch ein entsprechendes Objekt an, sofern noch nicht vorhanden,
das macht ${session.articleList} vielleicht nicht, 
und ist deshalb hier evtl gefährlicher als in Struts, wo das auf andere Weise geregelt ist


----------



## Guest (10. Mai 2007)

OK, das klingt logisch!


Um nochmal auf meine eigentliche Frage der Validierung zurückzukommen:

Da ich ja ohne DB arbeite, also alles im Speicher abläuft, bin ich auf eine Problematik gestoßen:
Folgendes Szenario: Der Anwender sieht die Artikel-Liste ("articleList.jsp"):


```
- (1) Hammer
- (2) Schraubenzieher
- (3) Säge
- (4) Beil
```

Er klickt auf "Schraubenzieher". Der Controller nimmt das Objekt Nr. 2 und macht es der "article.jsp" verfügbar, die es anzeigt.

Der Name des Artikels darf ja nicht leer sein. Jetzt fängt mein Problem an: Der Anwender löscht im Artikel-Formular den Namen heraus und schickt das Formular ab. Die Validierung meckert den leeren Namen an, indem der Controller wieder auf "article.jsp" weiterleitet und eine Fehlermeldung anzeigt. Die Validierung lässt den Anwender so lange nicht in Ruhe, bis er wieder einen Namen eingetragen hat.

Jetzt kommts: Was ist aber, wenn der Anwender im Browser einfach auf "Zurück" geht. Oder wenn ich einen "Abbrechen"- Knopf anbieten möchte. In der Bean ist ja der Name leer. Und dieser leer Namen würde auch wieder in der "articleList.jsp" angezeigt werden...


```
- (1) Hammer
- (2) 
- (3) Säge
- (4) Beil
```


Ist das Problem verständlich?


----------



## HLX (10. Mai 2007)

Da du MVC machen möchtest:

Deine View erhält seine Daten aus dem Model, d.h. du solltest eine Bean haben, die die in der JSP angezeigten Werte hält. Diese Bean darf nur modifiziert werden, wenn die Validierung fehlerfrei abgeschlossen wurde. Die Validierung erfolgt auf deinen Formulardaten. Bei fehlerfreier Validierung modifizierst du die Bean und die Views erhalten aktualisierte Daten.

So kann der Benutzer machen was er will. Er bekommt immer korrekte Informationen angezeigt.


----------



## SlaterB (10. Mai 2007)

@shadow:
nicht so wirklich,
egal ob der Name leer oder nicht bekannt ist (Browser History zurück) oder gar die Session schon abgelaufen ist, 
alles Fälle die man abfangen und mit Fehlermeldungen behandeln muss

und Daten aus Formularen nie ungeprüft irgendwohin speichern,
warum überhaupt den Namen in der Liste aktualisieren?

da muss eine Unterscheidung zwischen Daten und Benutzereingaben her,
notfalls durch unterschiedliche Beans


----------



## shadow (10. Mai 2007)

@HLX:

Dieser Gedanke ist mir auch schon gekommen, die Bean nur zu aktualisieren, wenn die Validierung fehlerfrei ist. Wenn der Anwender allerdings den Namen herauslöscht und dann das Formular abschickt, möchte ich, dass nach der Validierung neben dem leeren Feld die Fehlermeldung angezeigt wird ("Darf nicht leer sein").

Zur Veranschaulichung (das erste wirkt doch irgendwie komisch, oder? Darf nicht leer sein, ist es aber auch gar nicht):


```
Name: Schraubenzieher          Name darf nicht leer sein.
```

Wohingegen das hier normaler wirkt (ist leer, darf aber nicht leer sein):


```
Name: __________________         Name darf nicht leer sein.
```


@SlaterB:

>> warum überhaupt den Namen in der Liste aktualisieren? 

Ich aktualsiere eigentlich nicht den Namen in der Liste, sondern das passiert automatisch, in dem ich den Namen von Objekt 2 (Schraubenzieher) verändere. Da dieses Objekt auch in der Liste ist, würde auch der Name in "articleList.jsp" angezeigt werden.... egal.


Ich fand das Problem so schwierig zu erkären. Deshalb freue ich mich jetzt umso mehr, dass wir am Knackpunkt angekommen sind.

Es läuft eigentlich darauf hinaus (Vorschläge von HLX und SlaterB): Entweder ich zeige immer nur valide Daten an, dann komme ich mit einer Bean aus. Oder ich verwende zwei Beans, eine nur für die Anzeige (wo auch mal falsche Daten drin stehn können), und die andere wo immer valide Daten drin sind.

Ich habe mir viel Gedanken gemacht, warum ich an dieser Stelle feststecke. Ich vermute es ist deshalb, weil man so eine Anwendung immer mit DB schreibt. Klickt der Anwender in der Artikel-Liste auf "Schraubenzieher", so wird die "article.jsp" angezeigt. Hier kann der Anwender nach Herzenslust die Bean verändern, Felder leeren, etc.  Solange die Validierung nicht fehlerfrei verlief, wird das Objekt einfach nicht in die DB abgespeichert. Geht er auf "Zurück", oder die Session verschwindet, wird beim nächsten Anzeigen der Artikel-Liste einfach wieder alles aus der DB geladen, und die alten Werte sind wieder da.

Ich habe dieses Problem also nur, weil ich ohne DB arbeite, nämlich alles im Speicher abläuft...

Klingt die Überlegung plausibel?


----------



## HLX (10. Mai 2007)

Du musst natürlich nach modifizierbarkeit unterscheiden. Informationen die innerhalb eines request nicht modifizierbar sein sollen, wie zum Beispiel der Inhalt deiner Auswahllisten kannst du direkt aus dem Model beziehen. Dinge die modifizierbar sein sollen, z.B. das ausgewählte Element einer Liste oder ein Textfeld würde ich zuvor vom Model an den Request oder die Session als Parameter übergeben. Bei diesen Feldern arbeitest du sozusagen auf Kopien, dessen Änderungen erst ins Backend übertragen werden, wenn die Validierung erfolgreich war.

Struts 1 arbeitet im prinzip ähnlich. Hier werden modifizierbare Parameter an ein ActionForm-Objekt übergeben. Dieses verfügt über eine reset-Methode, in der z.B. Formular-Felder aus dem Backend gefüllt werden können. M.E. ist ein Vorteil von Struts, dass du mit der Validate-Methode der ActionForm vor allem syntaktische und semantische Fehler schon vor dem Controller abfangen kannst. Das Framework kann glaube ich für deine Zwecke sehr hilfreich sein.


----------



## shadow (10. Mai 2007)

OK, das  hilft mir weiter...

Vielen Dank für de Denkanstöße!


----------

