Autor Thema: Notes Web Communicator  (Gelesen 3637 mal)

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Notes Web Communicator
« am: 27.11.11 - 13:38:12 »
Hallo,
 
Wichtig: Funktioniert für Version ab Notes 7. Ist extra Java1.4 kompatibel programmiert.

ich hab in der Vergangenheit in verschiedenen Projekten apache.jakarta HttpClient eingesetzt, um von Notes Anwendungen heraus mit HTTP zu kommunizieren. Oft waren das irgendwelche Arten Webservices. Zwar verfügte Notes ab 6.5 (glaub ich) über SOAP Consumer und Producer, aber diese Implementierung hatte in der Praxis auf Consumer-Seite ihre Tücken, insbesondere wenn der Producer Datentypen schickte, die Notes unbekannt waren. Noch problematischer war, dass viele Webservice-Producer überhaupt nicht mit SOAP arbeiteten sondern einfach nur eine HTTP Schnittstelle anboten oder/und auch die immer beliebtere REST-Architektur benutzen.
Um sowas zu integrieren benötigt man vor allem einen flexibel programmierbaren HTTPClient und den liefert halt jakarta HTTPClient.
Selbstverständlich lassen sich damit auch Dinge angehen, die vielleicht erstmal gar nicht als Webservices wahrgenommen werden, es aber in gewisser Weise sind. Z.B. das Herunterladen von PDF Dateien über eine Web-URL, wobei der Server ein aktives Http-Session Cookie erwartet.

Ich habs häufiger angekündigt das OpenSource zu stellen und jetzt komm ich endlich dazu. Das ganze ist angestossen worden, durch einen Thread im hiesigen Notes 7 Forum.
Wer also einen entsprechenden Anwendungsfall hat, kann sich jetzt an mich wenden. Das ganze befindet sich aktuell nominell in der Version 0.5.0 und das ist eher optimistisch. Konkrete Anwendungsfälle unterstützen die weitere Ausgestaltung des Designs sicher positiv.

Kurze architektonische Beschreibung.
Thematisch geht es immer um einen HTTP Request, der von Notes initiiert wird und dessen zurückkommender HTTP-Response verarbeitet werden soll.  
Das Framework ist modular konzeptiert, um möglichst viele Anwendungsfälle mit minimalen Programmieraufwand zu unterstützen.

Ein HTTP-Request (GET, in Kürze auch auch POST) wird über HashMaps (ähnlich wie LotusScript List) konfiguriert.
Dabei wird
- url gesetzt
- bestimmt ob redirect Antworten des Servers automatisch gefolgt werden soll
- der Proxy der Organisation für ausgehende HTTP-Requests wird gesetzt, optional mit Username und Kennwort.
- Es gibt die Möglichkeit die Anzahl von Retry-Versuchen anzugeben.
- Username/Passwort können gesetzt werden, falls die Zielwebseite Authentifizierung erfordert (noch nicht implementiert, kein Problem)
- ssl wird unterstützt (noch nicht implementiert)
 
Für den zurückgelieferten Response vom entfernten Server gibt es ebenfalls mit HashMaps konfigurierbar Handler
- Unterschiedliches Verhalten je nach zurückgelieferten HTTP-Status Code.
- Es werden die zurückgelieferten Cookies ausgelesen.
- Der Body des Response wird als Stream zurückgegeben
- Der Body des Response wird als String zurückgegeben.
- etc.

Hier 2 Beispiele aus meinen junit-Integrationstests
java.util.Properties ist eine HashMap. Die entsprechenden Werte müssen natürlich nicht hartkodiert werden, sondern können etwa aus einem NotesDocument gelesen werden. Sie müssen auch nicht in java Properties File gespeichert werden, sondern können selbstverständlich in NotesItems gespeichert werden.    

Anwendungsfall 1 auslesen der Cookies aus dem Response
Code
	public void testRetrieveResponse() throws Exception {
		Properties props = new Properties(); // HashMap zur Konfiguration
		props.put("url", "http://someWebsite.de/");
		props.put("de.aja.preparecall.AddFollowRedirects.followRedirects", "false"); // FollowRedirect wird standardmässig immer benutzt. Festgelegt, dass Redirects nicht gefolgt wird. 
		props.put("clazzProcessReturn", "de.aja.docall.ReturnCookiesHandler"); // die Cookies der Response werden ausgelesen
		
		
		HttpClientInvoker invoker = HttpClientInvoker.getDefaultHttpClientInvoker(props); // Einstiegsklasse des Frameworks
		
		Object res = invoker.doInvoke(new GetMethod()); // Aufrufmethode des Frameworks. Gibt HTTP Get Aufruf
		System.out.println("res=" + res); 
		Properties propsCookies = new Properties();
// Inhalt der Cookies wird als String in ein java Properties File geschrieben, kann auch in NotesItems geschrieben werden.
		propsCookies.put("globals.requestHeader.Cookie", res); 
		System.out.println(propsCookies);
		propsCookies.store(new FileOutputStream("cookies.properties"), "Generated by Program");
		
		
	}


Anwendungsfall 2: Speichern eines zurückgelieferten PDF Files, falls der Server mit HTTPStatus 200 geantwortet hat.
Code
	public final void testRetrieveResponse() throws Exception {
		Properties props = new Properties();
		props.put("url", "http://someurl?action=textpdf&docid=DE03003827T1");
		props.put("clazzesPrepareCall", "de.aja.preparecall.AddRequestHeader"); // konkret hier: füge SessionCookie dem Request Header hinzu. 
		props.put("de.aja.preparecall.AddFollowRedirects.followRedirects", "false"); // followRedirects nie folgen
		props.put("clazzProcessReturn", "de.aja.docall.ReturnBodyAsStreamHandler"); // Response als Stream zurückgeben, falls Statuscode 200 von Server
		props.put("folderDest", "D:/test/notes/"); // Ordner in denen PDF gespeichert werden		
// Cookies aus Java Properties Datei laden, kann auch von Notes Items geholt werden 
		Properties propsCookies = new Properties();
		File cookiesProperties = new File("cookies.properties");
		if (cookiesProperties.exists()) {
			propsCookies.load(new FileInputStream("cookies.properties"));
		}
		System.out.println("propsCookies=" + propsCookies);
		props.putAll(propsCookies);
		
         
		HttpClientInvoker invoker = HttpClientInvoker.getDefaultHttpClientInvoker(props); // Einstiegsklasse des Frameworks
		
		Object res = invoker.doInvoke(new GetMethod()); // Aufrufmethode des Frameworks
		if (res instanceof java.lang.Integer) { // Returncode wird zurückgeliefert, wenn HTTPStatus != 200
			System.out.println("Return Integer is:" + res); 
		} else if(res instanceof java.io.InputStream) { // InputStream sollte PDF File sein, spezifische Logik, um Dateiname zu ermitteln, speichern auf Festplatte. 
			InputStream in = (InputStream) res;
			String[] urlParts = invoker.getUrl().split("=");
			String fileDest = props.getProperty("folderDest")
					+ urlParts[urlParts.length - 1] + ".pdf";
			System.out.println("file destination is " + fileDest);
			OutputStream out = new FileOutputStream(fileDest);

			// Transfer bytes from in to out
			byte[] buf = new byte[1024];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();

		} else {
			System.out.println("Unexpected return" + (res == null ? "null" : res.getClass().getName()));
		}


	}

Wenn man jetzt hinter einem Authentifizierenden Proxy sitzt, kann man einfach die Konfiguration ein wenig ändern und neue Properties für ProxyHost, proxyPort, ProxyUser und ProxyPassword setzen.
In Beispiel2 sähe das so aus:
Code
		// statt props.put("clazzesPrepareCall", "de.aja.preparecall.AddRequestHeader");
                props.put("clazzesPrepareCall", "de.aja.preparecall.AddRequestHeader:de.aja.preparecall.AddReverseProxyBaseAuth");
// UND ZUSÄTZLICH
props.put("de.aja.preparecall.AddReverseProxyBaseAuth.user", "axel");
props.put("de.aja.preparecall.AddReverseProxyBaseAuth.pwd", "kennwort");
props.put("de.aja.preparecall.AddReverseProxyBaseAuth.proxyHost", "192.168.12.7");
props.put("de.aja.preparecall.AddReverseProxyBaseAuth.proxyPort", "8080");
  

Wenn die Ziel-Website Authentifizierung erfordert, kann man einfach die Konfiguration ein wenig ändern und neue Properties für HostPassword und HostUsername setzen.  

Falls für ein Spezialfall die bisher vorhandenen Klassen zur Request Vorbereitung und die ResponseHandler nicht ausreichen, kann das Framework über das Implementieren von bestehenden Interfaces problemlos erweitert werden.

Hört sich vielleicht verwirrender an als es ist.
Wer Interesse hat, kann sich jederzeit melden.

Gruß Axel
« Letzte Änderung: 27.11.11 - 13:56:17 von Pitiyankee »
Ich stimm nicht mit allen überein, aber mit vielen und sowieso unterhaltsam -> https://www.youtube.com/channel/UCr9qCdqXLm2SU0BIs6d_68Q

---

Aquí no se respeta ni la ley de la selva.
(Hier respektiert man nicht einmal das Gesetz des Dschungels)

Nicanor Parra, San Fabian, Región del Bio Bio, República de Chile

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz