# jQuery: Response direkt anzeigen bzw. auf Response warten bzw. jQuery und Servlet



## NetPerformance (13. Januar 2011)

Hallo Zusammen,

ich versuche mal mein das Problem so genau wie möglich zu schildern.

Die fertige Seite sieht folgendermaßen aus:






Der Anwender kann  innerhalb der Eingabefelder neue Gästebuch-Einträge vornehmen. Diese werden via jQuery bzw. Ajax an ein Servlet gesendet. Das Servlet nimmt die Daten entgegen und speichert diese innerhalb der Datenbank ab. Soweit ist alle suppi. 
Anschließend sollen die Einträge *(ohne dass ich die Seite neu lade)* angezeigt werden. Und genau das kann ich noch nicht realisieren! Momentan werden die Einträge erst angezeigt, nachdem ich die Seite neu geladen habe.

Wichtige Dateien:
Bei der „view“ handelt es sich um die Datei content.jsp . Diese JSP wird via Tiles-Definition eingefügt (sollte aber egal sein).
Die JS-Datei „default.js“ beinhaltet das selbst geschriebene JS.
Der „controller“ wird durch die Servlet-Klasse GuestbookController.java repräsentiert.

Ablauf:
Die JSP-Datei „content.jsp“ wird beim Laden der Seite aufgerufen. Die JSP beinhaltet das JS. Dabei wird innerhalb von „$(document).ready(function() {…“ das Servlet aufgerufen.


```
Code:
$(document).ready(function() {
      $.get("/Guestbook/GuestbookController?action=getEntries", function(data) {
        // muss ich hier eventuell auf das Reponse warten?    
      });
...
```

Der Controller bzw. das Servlet liest alle Gästebuch-Einträge aus der DB aus und senden diese als Response zurück.

```
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      String action = (String) request.getParameter("action");
      if(isValidString(action) && action.equals("getEntries")) {
            try {
                  request.getSession().setAttribute("entries", databaseConnector.getEntries());
            } catch (SQLException e) {
                  e.printStackTrace();
            }
      }
}
```

Die folgende JS-Passage ist für das Versende des Eintrags an das Servlet zuständig:

```
$("#sendButton").click(function(){
            var entryName = $("#entryName").val();
            var entryEmail = $("#entryEmail").val();
            var entryHomepage = $("#entryHomepage").val();
            var entryMessage = $("#entryMessage").val();         
            $.ajax({
                  url: "GuestbookController",
                  type: "POST",
                  async: true,
                  data: {
                        entryName: entryName,
                        entryEmail: entryEmail,
                        entryHomepage: entryHomepage,
                        entryMessage: entryMessage
                  },
                  success: function () {
                        // mmhh.. 
                  }     
            });         
      });
```


Ich möchte das die Einträge gleich angezeigt werden und nicht erst nachdem ich die Seite neu geladen habe!
Was muss ich machen, damit die Einträge gleich angezeigt werden (via Ajax)? bzw. Was die Schlagwörter, wonach ich suchen sollte?

Ich bedanke mich im Vorraus,
Aaron


----------



## SonicBe@m (14. Januar 2011)

Das ist ganz einfach.
Wenn du direkt nach dem absenden die Einträge wieder anzeigen willst dann nimmst du die die Zeilen 
                  success: function () {
                        // mmhh.. 
                  }     

und packst in das success einfach noch

success: function () {
   $.get("/Guestbook/GuestbookController?action=getEntries", function(data) {
       // hier kommt nun der code rein wo der inhalt angezeigt werden soll z.b.
       $("#guestbook").val(data);

   });
}     



was eigentlich fehlt ist ggf. ein autorefresh alle N sekunden.

hoffe ich konnte dir helfen


----------



## CPoly (14. Januar 2011)

Dein GuestbookController muss nach dem Eintragen in die DB einfach ein bisschen HTML zurück liefern, welches den gerade erzeugten Eintrag enthält. Den musst du dann nur noch an die entsprechende Stelle einfügen.

Also an folgender Stelle:

```
success: function () {
    // mmhh.. 
}
```

Sowas machen:


```
success: function (data) {
    var neuerEintrag = $(data).hide();
    $("#guestbook_wrapper").prepend(neuerEintrag);
    neuerEintrag.slideDown();
}
```

Jetzt sollte der neue Eintrag ganz oben eingefügt werden und dann sichtbar werden.


----------



## NetPerformance (14. Januar 2011)

Hallo Zuammen, 

danke für die Beispiele. Das Prinzip ist mir jetzt klar geworden.
Da ich keine einzelne Datensätze erhalte, kann ich die Beispiele bei mir nicht anwenden.

Noch einmal zum Ablauf:
1. Ich rufe eine JSP auf. Das JSP beinhaltet das JavaScript.
2. Das JavaScript ruft das Servlet auf. Das Servlet schreibt eine ArrayListe mit Einträgen in die request.session.
3. Das JSP liest das Array aus und rendert alle Einträge auf einmal. (Daher erhalte ich die Einträge nicht einzeln)

zu 3.:

```
<%-- Nachrichten --%>
<div id="entries">
	<c:forEach items="${entries}" var="entries">
		<c:set var="entryBean" value="${entries}" />
		<div id="messageContainer">
			<div id="message">
				<div id="messageHeader">
					<div id="userName">${entryBean.name} | ${entryBean.date}</div>
					<div id="userIcons"><a href="mailto:${entryBean.email}?subject=<fmt:message key='title'/>" target="_blank"><img src="./img/email.png" alt="<fmt:message key='email'/>"  border="0"/></a><a href="${entryBean.homepage}" target="_blank"><img src="./img/homepage.png" alt="<fmt:message key='homepage'/>"  border="0"/></a></div>
				</div>
				<div id="messageContent">${entryBean.message}</div>
			</div>
		</div>	
	</c:forEach>	
</div>
```
 


Das folgende Beispiel funktioniert bei mir (halbwegs):


```
$('#sendButton').live('click', function() {
	var entryName = $("#entryName").val();
	var entryEmail = $("#entryEmail").val();
	var entryHomepage = $("#entryHomepage").val();
	var entryMessage = $("#entryMessage").val();		
	$.ajax({
		url: "GuestbookController",
		type: "POST",
		async: false,
		data: {
			entryName: entryName,
			entryEmail: entryEmail,
			entryHomepage: entryHomepage,
			entryMessage: entryMessage
		},
		success: function () {
			$.get("/Guestbook/GuestbookController?action=getEntries"); // alle Einträge (auch die soeben eingefügte) werden aus der DB gelesen.
			location.reload("#entries");
			location.reload("#entries");
		}
	});		
});
```


Ablauf:
1. Der Anwender nimmt einem neuen Eintrag vor.
2. Der Eintrag wird innerhalb der DB gespeichert.
3. Wenn die Speicherung erfolgreich war, werde ich in die obige "success" Passage weitergeleitet.
4. Innerhalb von "success" werden alle Einträge aus der DB erneut ausgelesen (zunächst ohne Paging) -> $.get("/Guestbook/GuestbookController?action=getEntries");
5. Nachdem alle Einträge von der JSP ausgelesen wurden (sie befinden sich in der Session), wird das Div (<div id="entries">), welches für die Anzeige der Einträge verantwortlich ist neu geladen. location.reload("#entries").

Und hier habe ich momentan das Problem, dass die neuen Einträge manchmal direkt angezeigt werden und manchmal nicht. Erst wenn ich  2x die location.reload("#entries") Anweisung aufrufe, werden die Einträge zu 90% gleich angezeigt.
Wenn ich location.reload("#entries")  nur einmal aufrufe, werden neue Einträge manchmal direkt angezeigt und manchmal nicht. Angenommen ich nehme einen neuen Eintrag vor und diese wird nicht angezeigt. Wenn ich dann einen zweiten Eintrag vornehme, kann es passieren, dass beide auf eimal angezeigt werden. Der dritte Eintrag wird dann plötzlich direkt angezeigt.

Ich muss anscheinend "irgendwie" auf das request warten?! 

Würde mich über weitere Ideen sehr freuen?

Besten Dank,
Aaron


----------



## SonicBe@m (14. Januar 2011)

Nein warten nicht.
Der Callback success wird nur aufgerufen wenn er fertig ist.

Eine alternative für dein Problem wäre einen MVC zu schreiben welcher dir die Daten also JSON zurückliefert.

Mit JSON kannst du dann dynamisch die einträge darstellen und sparst dir somit HTML.
Es ist zwar etwas mehr aufwand weil du :
JSON ViewControler schreiben musst.
Das HTML via Javascript generieren musst.

aber schlußentlich erhälst du dafür ein insgesammt besseres Handling auf der Clientseite.


in JSON könnte dein output z.b. so aussehen:



[{"id":"1","name":"AOK Bayern","strasse":"Postfach 200121","postleitzahl":"80337","ort":"M\u00fcnchen","preis_km":"2.12345"},{"id":"2","name":"Sonstige","strasse":"Am Bruch 8","postleitzahl":"50171","ort":"Kerpen","preis_km":"2.12345"},{"id":"3","name":"Rosenhof","strasse":"Brunnaderstr. 24","postleitzahl":"84364","ort":"Bad Birnbach","preis_km":"1.1235"}]

zur besseren übersicht kannst du dir das JSON hier formatieren lassen.
http://jsonformatter.curiousconcept.com/

Das elegante wäre das du z.b. beim ersten laden der Seite dir alle Daten aus der Datenbank holst, im weiteren schritt holst du dir nur noch die gerade eingefügten einträge.
Nun kannst du die einträge mit javascript auch noch highlighten.

Falls dich das interessiert kann ich ja noch etwas mehr darauf eingehen.


----------



## SonicBe@m (14. Januar 2011)

Ausserdem mir ist gerade aufgefallen.
Du machst nichts mit deinem get!


        success: function () {
            $.get("/Guestbook/GuestbookController?action=getEntries",* function(data) {
// hier kommt nun die stelle wenn er die daten geladen hat!
  location.reload("#entries");
            }*); // alle Einträge (auch die soeben eingefügte) werden aus der DB gelesen.

        }


das success sagt ja nur das deine anfrage zum speichern beim server angekommen ist
das du mit deinem reload das ergebniss mal siehst und mal nicht liegt darann das er die daten noch nicht vom server bekommen hat sprich dein datenbank select ist noch nicht zurückgekehrt.

so wie das nun oben steht wird nur dann der reload aufgerufen wenn auch garantiert ist das der result vorhanden ist


----------



## NetPerformance (14. Januar 2011)

Danke SonicBe@m: Du hast es erfasst! 

Ich muss das reload innerhalb der function aufrufen. 
Die Sache mit JSON ist mir bekannt. Werde das Beispiel bei Gelegenheit umschreiben.

Vielen Dank,
Aaron


----------

