Probleme mit JSON Antwort einer Ajax-Anfrage

Ulrikop

Grünschnabel
Hallo,
ich bin mir nicht sicher wo es besser aufgehoben ist, hier oder im Java-Forum.
Da ich hier mer Web-Programmierer vermute als im Java Forum, versuche ich es hier.


Ich habe eine Seite die über JSF (JavaServer Faces) erstellt wird.
Sie besteht vor allem aus einer Karte (ähnlich wie GoogleMaps), die auf meinem Server läuft.

Nun würde ich der Karte gerne mehr Funktionalitäten geben (wie z.B. GeoCoding, dass aus einer angeklickten Stelle die nächste Straße ermittelt wird).
Diese Funktionalität kann ich Serverseitig über Java bereitstellen.

Mittels Javascript soll per AJAX-Anfrage der Dienst angesprochen werden (per Get-Parameter werden benötigten Werte und Angaben übergeben) und die Antwort soll als JSON zurückkommen. Javascript soll diese Antwort entsprechend weiter verarbeiten (z.B. die entsprechende Straße einzeichnen).

Es wird später mehr Seiten bei uns geben, die diese Karte verwenden und für die diese Funktionalitäten ebenfalls interessant sein könnten. Aus diesem Grund will ich es nicht in das bestehende JSF-Projekt mit einbinden, sondern als extrigen Dienst anbieten.

Da ich für diesen Dienst eh Java brauche und die Seiten mittels JSF erstellt werden, will ich den Dienst auch per JSF anbieten. Vielleicht gäbe es hier auch was sinnvolleres, weil so brauche ich im Moment eine leere index.xhtml, damit der Dienst angesprichen werden kann.

Durch das Anmelden eines PhaseListener fange ich nun alle Anfragen nach der ersten Phase (PhaseId.RESTORE_VIEW) ab.

Erstelle das JSON-Objekt und schicke es zurück.
Im Moment sind es nur Test-Code schnippsel, bei denen ich aber schon Probleme habe.

Mein JavaScript sieht so aus:
HTML:
var req = null;

function sendMapRequest()
{
	var url = "http://localhost:8080/MapFunctionsServer/index.xhtml";
	
	if (window.XMLHttpRequest)
		 req = new XMLHttpRequest();
	else if (window.ActiveXObject)
		req = new ActiveXObject("Microsoft.XMLHTTP");
	 
	if(req)
	{
		req.open("Get", url, true);
		req.onreadystatechange = callback;
		req.setRequestHeader("content-type","text/plain");
		req.send(null);
	}
}

function callback()
{	
	if(req.readyState == 4)
	{
		var translation = eval('(' + req.responseText + ')');
		message = translation.message;
		alert(message);
	}
}

Der Dienst im JSF-Projekt:
Code:
public void afterPhase(PhaseEvent _event)
{
    FacesContext context = _event.getFacesContext();
    HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
  

    try
    {
	    JSONObject myMessage = new JSONObject();
	    myMessage.put("message", "I am sending a message");
	    response.setContentType("text/plain");
	    response.setHeader("Cache-Control", "no-cache");    
    
	    response.getWriter().write(myMessage.toString());
	    context.responseComplete();
    }
    catch (Exception e)
    {
	    e.printStackTrace();
    }
}


Das Programm führt den AJAX-Befehl aus,
Es wird die Callback-Methode mit dem Status 1, 2 und 4 aufgerufen.

Auf JSF-Seite sieht man, wie er in afterPhase Methode rein geht und alles wie gewünscht abarbeitet.

Wenn der Status 4 kommt ist immer req.responseText ein leerer String.
Wenn ich die Seite http://localhost:8080/MapFunctionsServer/index.xhtml im Browser aufrufe kommt aber genau das, was ich will, im Quelltest steht lediglich: {"message":"I am sending a message"}

Das führt dann natürlich bei var translation = eval('(' + req.responseText + ')'); zu einem Fehler:
Error: syntax error
Source Code:
()
in der Zeile von dem eval.

Bin am Verzweifeln und weiß grad nicht, an was das liegt und wie ich weiter machen muss.

Wäre froh, wenn mir wer helfen könnte.
Falls ihr denkt, dass es im Java Forum doch besser aufgehoben ist, könnt ihr es gerne verschieben.

Danke


(Vorgegangen bin ich bis jetzt nach http://today.java.net/article/2007/06/06/bundling-ajax-jsf-components )
 
Zuletzt bearbeitet:
Hallo CPoly,
folgendes sagt Firebug (habe die Funktionalität noch nie genutzt, falls es irgend wo noch detailiertes Infos gibt, kann ich da auch noch gern nachsehen):

URL: GET index.html
Status: Aborted
Domain: localhost:8080
Size 36 B
Location: http://localhost:8080/MapFunctionsServer/index.xhtml
Request Header: nichts
Respones Header: nichts
Response Body: {"message":"I am sending a message"}


Wohl das interessanteste, der Status.
Nur wieso aborted?
 
Erst mal folgendes: Um zu verhindern, dass solche Request überhaupt verarbeitet werden, musst du deinen Code minimal anpassen
Javascript:
if(req.readyState === 4 && req.status === 200)


Wie rufst du denn sendMapRequest auf? Ein klassischer Fehler wäre z.B. in einem submit Event, aber ohne das Event zu stoppen. Dann würde die AJAX Anfrage durch den neuen Seitenaufruf abgebrochen. (race condition)
 
Nein, in den Submit habe ich es nicht rein getan.
Die Testseite besteht nur aus einem Button. Die "onclick"-Methode löst dann den AJAX-Aufruf aus:
Code:
<body>

<button name="testclick" type="button"
      value="AJAX" onclick="return sendMapRequest();">

</body>

Was im Moment aber komisch ist:
Hab grad die Computer an gemacht, das heißt der JSF-Server mit der localhost seite die oben angesprochen wird, läuft im Moment nicht.
Wenn ich die Seite direkt aufrufe, kommt auch, dass sie nicht vorhanden sei (wie erwartet).
Wenn ich auf den button der Testseite klicke kommt aber trotzdem ein AJAX response in dessen Body laut Firebug aber das Ergebnis der JSF-Seite steht.
Seltsam.



edit: ups wie peinlich.
du hattest (zumindest halb) recht: es war der button, wieso aborted kam.
ich habe ein return false in der Methode vergessen.

jetzt steht im Firebug zwar ein "200 ok" beim Status.
Wenn ich allerdings auf "Response" klicke steht dort nichts drin (wenn ich die Seite per Hand selber aufrufe, kommt aber das gewünschte zurück).
Response Header:
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1 Java/Oracle Corporation/1.7), JSF/2.0
Server: GlassFish Server Open Source Edition 3.1
Cache-Control: no-cache
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 36
Date: Thu, 29 Sep 2011 07:25:12 GMT


Content Length wird aber noch angegeben.... Mal schauen, vielleicht krieg ich das nun noch raus :-)

nächstes edit:
auch wenn firebug 200 ok anzeigt, kommt beim code bei req.status 0 an. Der Ajax-Request wird aber nur 1x abgeschickt
 
Zuletzt bearbeitet:
Vielleicht wird dein "response.setHeader("Cache-Control", "no-cache");" nicht ernst genommen.

Noch eine Frage zum generellen Aufbau. Du rufst also via AJAX "http://localhost:8080/MapFunctionsServer/index.xhtml" auf. Aber wo liegt die die Datei, in der du den Button hast? Wie lautet die URL, unter der du die Datei aufrufst?
 
Also im InternetExplorer 7 funktioniert der AJAX Befehl.
Es kommt das richtige zurück.

dafür funktioniert folgendes nicht.

Code:
if (window.XMLHttpRequest)
	 req = new XMLHttpRequest();
else if (window.ActiveXObject)
	req = new ActiveXObject("Microsoft.XMLHTTP");

window.XMLHttpRequest gibt auch im Internetexplorer anscheinend true zurück. Kurz darauf wird allerdings der Fehler "Zugriff verweigert" geworfen.

Auf
habe ich folgenden Code zum Erstellen gefunden:
Code:
try{
	req = new XMLHttpRequest();
}
catch (e){
	try{
		req = new ActiveXObject("Msxml2.XMLHTTP");
	} 
	catch (e){
		try{
			req = new ActiveXObject("Microsoft.XMLHTTP");
		} 
		catch (failed){
			req = null;
		}
	}  
}
Funktioniert auch nicht, da beim Erstellen noch kein Fehler geworfen wird.
Aber ok, das ist ein Problem das sicher viele haben, da werde ich wahrscheinlich über google schnell fündig.


Zu deiner Antwort:
Ich habe das "Cache-Control", "no-cache" mal raus genommen. Geht allerdings auch nicht.

Die andere Seite heißt einfach "test.htm" und die rufe ich über den normalen Pfad auf wie C:\test.htm
Meinst du, da dies nicht über eine Adresse wie localhost geht, funktioniert es nicht? Das Probiere ich mal schnell aus.
 
Die andere Seite heißt einfach "test.htm" und die rufe ich über den normalen Pfad auf wie C:\test.htm
Meinst du, da dies nicht über eine Adresse wie localhost geht, funktioniert es nicht? Das Probiere ich mal schnell aus.

Das weiß ich sogar. Du musst über localhost gehen. AJAX über den normalen Dateipfad kannst du knicken.

Edit: Auch der Port muss der gleiche sein.
 
....

habe es nun in eine fertige JSF-Anwendung eingebaut, die ich auch über localhost aufrufen kann.
Da funktioniert es.


Vielen lieben Dank für die Geduld und Mühe bei dieser trivialen Anfängerfrage.


edit: da ist ja einmal der Internet Explorer intuitiver, der es auch über die Adresse C:\test.htm macht
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück