Autor Thema: wann brauchen wir SOAP Webservices und wann nicht?  (Gelesen 13319 mal)

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Hi,

Zitat
SOAP is something I put on my balls.
von Charles "cowboyd" Lowell aus Austin in Texas im DrunkAndRetired Podcast, Folge 85.

das ist wirklich keine dumme Aussage.
Viele sagen zur Zeit, dass SOAP für die meisten Fälle einen völligen overkill darstellt, obwohl es zugegebnermassen eine gute Tool-Unterstützung hat.

Meistens möchte man:
- Daten in xml packen.
- Diese Daten über http oder https an einen Server schicken
- vom Server xml als Antwort zurückbekommen

Nur wird heute die SOAP Spec als etwas kritisiert, bei der alles denkbare konfigurierbar sein soll.
Und genau das führt natürlich zu sehr viel Komplexität.

Das zur Zeit fortschrittlichste und einfachste SOAP Framework generiert aus diesem unschuldigen remote Kommunikationsinterface. 

Code
package de.kingmedia.daw.bo;

import java.util.Date;
import java.util.List;

/**
 * @author Axel
 *
 */
public interface DiscountService {
	String requestDiscount(String idOffer, String nameAgent, int discountReq, boolean urgency, String note);	
	DiscountRequest retrieveRequestDiscountResponse(String idOffer);
	List <DiscountRequest> retrieveRequestDiscountListing(Date beginDate, Date endDate, String status);
}
dieses Monster-WSDL:
Code
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://kingmedia.de/DiscountService" xmlns:tns="http://kingmedia.de/DiscountService" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://bo.daw.kingmedia.de" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc11="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenc12="http://www.w3.org/2003/05/soap-encoding" xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://kingmedia.de/DiscountService">
<xsd:element name="retrieveRequestDiscountResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="in0" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="retrieveRequestDiscountResponseResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="ns1:DiscountRequest"/>
</xsd:sequence>

</xsd:complexType>
</xsd:element>
<xsd:element name="requestDiscount">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="in0" nillable="true" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in1" nillable="true" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in2" type="xsd:int"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in3" type="xsd:boolean"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in4" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="requestDiscountResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="xsd:string"/>

</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="retrieveRequestDiscountListing">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="in0" type="xsd:dateTime"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in1" type="xsd:dateTime"/>
<xsd:element maxOccurs="1" minOccurs="1" name="in2" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="retrieveRequestDiscountListingResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="ns1:ArrayOfDiscountRequest"/>
</xsd:sequence>

</xsd:complexType>
</xsd:element>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://bo.daw.kingmedia.de">
<xsd:complexType name="DiscountRequest">
<xsd:sequence>
<xsd:element minOccurs="0" name="m_beginDate" type="xsd:dateTime"/>
<xsd:element minOccurs="0" name="m_discountAllowed" type="xsd:int"/>
<xsd:element minOccurs="0" name="m_discountReq" type="xsd:int"/>
<xsd:element minOccurs="0" name="m_history" nillable="true" type="ns1:ArrayOfDiscountRequest"/>
<xsd:element minOccurs="0" name="m_idAgreeement" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="m_idOffer" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="m_nameAgent" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="m_note" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="m_status" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="m_urgency" type="xsd:boolean"/>
</xsd:sequence>

</xsd:complexType>
<xsd:complexType name="ArrayOfDiscountRequest">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="DiscountRequest" nillable="true" type="ns1:DiscountRequest"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
  </wsdl:types>
  <wsdl:message name="requestDiscountResponse">
    <wsdl:part name="parameters" element="tns:requestDiscountResponse">
    </wsdl:part>
  </wsdl:message>

  <wsdl:message name="retrieveRequestDiscountResponseResponse">
    <wsdl:part name="parameters" element="tns:retrieveRequestDiscountResponseResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="retrieveRequestDiscountListingResponse">
    <wsdl:part name="parameters" element="tns:retrieveRequestDiscountListingResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="requestDiscountRequest">

    <wsdl:part name="parameters" element="tns:requestDiscount">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="retrieveRequestDiscountResponseRequest">
    <wsdl:part name="parameters" element="tns:retrieveRequestDiscountResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="retrieveRequestDiscountListingRequest">
    <wsdl:part name="parameters" element="tns:retrieveRequestDiscountListing">

    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="DiscountServicePortType">
    <wsdl:operation name="retrieveRequestDiscountResponse">
      <wsdl:input name="retrieveRequestDiscountResponseRequest" message="tns:retrieveRequestDiscountResponseRequest">
    </wsdl:input>
      <wsdl:output name="retrieveRequestDiscountResponseResponse" message="tns:retrieveRequestDiscountResponseResponse">
    </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="requestDiscount">
      <wsdl:input name="requestDiscountRequest" message="tns:requestDiscountRequest">
    </wsdl:input>
      <wsdl:output name="requestDiscountResponse" message="tns:requestDiscountResponse">
    </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="retrieveRequestDiscountListing">
      <wsdl:input name="retrieveRequestDiscountListingRequest" message="tns:retrieveRequestDiscountListingRequest">
    </wsdl:input>

      <wsdl:output name="retrieveRequestDiscountListingResponse" message="tns:retrieveRequestDiscountListingResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="DiscountServiceHttpBinding" type="tns:DiscountServicePortType">
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="retrieveRequestDiscountResponse">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="retrieveRequestDiscountResponseRequest">

        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="retrieveRequestDiscountResponseResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="requestDiscount">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="requestDiscountRequest">

        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="requestDiscountResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="retrieveRequestDiscountListing">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="retrieveRequestDiscountListingRequest">

        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="retrieveRequestDiscountListingResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="DiscountService">
    <wsdl:port name="DiscountServiceHttpPort" binding="tns:DiscountServiceHttpBinding">

      <wsdlsoap:address location="http://127.0.0.1:8080/DAWProto1/services/DiscountService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Klar. Das wird von Tools generiert. Aber es führt eine Komplexität in die Sache ein, die für sehr viele Fälle gar nicht nötig ist.

Warum nicht einfach selbst
- ein bischen xml generieren
- das gegen den Server senden (geht seit Notes5 mit Java oder anderen Mitteln, aber nicht mit Vanilla LotusScript)
- der Server sendet als Response xml zurück, das der Client verarbeiten kann.

Sowohl auf Client als auch auf Server Seite ist das mit Lotus Notes möglich. Mit Hilfe von Java oder anderen Mitteln. Nicht aber mit Vanilla LotusScript.

In der Folge (nicht heute) wird die Möglichkeit einer Alternativ-Implementierung ohne SOAP mit Notes7 dargestellt.

Gruß Axel

« Letzte Änderung: 11.03.07 - 02:59:34 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #1 am: 12.03.07 - 23:38:56 »
Proof of concept mässig geht das nämlich ohne dieses ganze SOAP Gedöns über HTTP.
Ich werd das noch full cycle ausarbeiten.
Das heisst:
Vom Notes Client wird mit Hilfe von LS2J und apache.jakarta.HTTPClient basierend auf (erstmal) basic authentification ein Post Request mit HTTP gegen einen Domino Server gesendet, der dann die gewünschten Daten ausliest und der dann xml zurückliefert. Das xml ist eingepackt in html. Ich werd aber in die nsf nicht die benötigten jakarta apache jars dazupacken, weil die zu groß sind. Müssen dann interessierte schon selber machen. Ich erklär dann auch wie.

Hier erstmal das (funktionierende) Proof of Concept.

Der LotusScript Notes Agent poxProducer (sendet das eingesendete xml einfach zurück, Verarbeitung muss noch programmiert werden):
Code
Sub Initialize
	Dim s As New NotesSession
	Dim doc As NotesDocument
	
	Set doc = s.DocumentContext()
	'Print "remoteUser=" + doc.Remote_User(0)
	
	Print doc.Request_Content(0) ' hier stehen die per HTTP-POST Request eingesandten Daten drinnen. 
End Sub


Webservice Requester: (aus einem Eclipse Projekt):
Code
package de.aja.http.client;
import java.io.IOException;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class WebConnector {
	
	HttpClient client = new HttpClient();
	PostMethod method = null;
	

	public void initClient(String userName, String pwd) {
               // basic authentification :-) 
		client.getState().setCredentials(
	            new AuthScope(null, 80, null),
	            new UsernamePasswordCredentials(userName, pwd)
	        );
	}
	
	public void createMethod(String url) {
		
		method = new PostMethod(url);
		method.setDoAuthentication( true );
		//method.addParameter("foo", "bar");
		method.setRequestEntity(new StringRequestEntity("<foo><bar>value</bar></foo>"));
	}
	
	public String connect() {
		try {
//			 set per default -> retries 3 times when recoverable error is thrown
			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
			  new DefaultHttpMethodRetryHandler());
			client.executeMethod(method);
			
			
			// nicht die feine englische ... for domino its simpler but to process a stream or byte (get.
			return method.getResponseBodyAsString();
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			// release the connection
			if (method!= null) {
				method.releaseConnection();
			}
		}
	}
	

}
Der client code von dieser Klasse sieht so aus (ein mit Junit geschriebener Integrationstest). Da ist ziemlich viel Eclipse generierter Boilerplate code dabei wichtig ist die Methode testConnect:
Code
package de.aja.http.client;

import org.apache.log4j.Logger;

import junit.framework.TestCase;

public class WebConnectorTest extends TestCase {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(WebConnectorTest.class);

	WebConnector cut = new WebConnector();
	public WebConnectorTest(String arg0) {
		super(arg0);	
	}

	protected void setUp() throws Exception {
		super.setUp();
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}

	public void testConnect() {
		cut.initClient("admin Axel", "voll_geheim");
		cut.createMethod("http://127.0.0.1/PoxServer.nsf/poxProducer");
		String res = cut.connect();
		logger.debug("retrieved-->\n" + res);
		
	}

}

ssl liesse sich auch locker einbinden.

« Letzte Änderung: 12.03.07 - 23:55:23 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #2 am: 12.03.07 - 23:46:13 »
Welchen Sinn macht es, sich über einen POX Webservice von einem Notes Client mit einem Notes Server zu verbinden, wenn das doch total viel einfacher mit Standard Notes Mitteln geht  ???

Nun wenn man per HTTP Daten von einem Notes Client mit einem Notes Server austauschen kann, dann kann man zum Bleistift:
a) den Client Part verwenden, um sich mit einer PHP Anwendung, einer Java Webserver Anwendung oder einer ASP.NET Anwendung oder whatever auszutauschen
UND
b) den Server Part verwenden, um Anfragen von einer PHP Anwendung, einer Java Anwendung einer DOT.NET Anwendung oder whatever zu bedienen.

Und das alles mit Authentifizierung, bei Bedarf SSL und OHNE SOAP.

Man hat also quasi alle Fälle in einem Beispiel  ;D
« Letzte Änderung: 12.03.07 - 23:56:02 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #3 am: 14.03.07 - 16:21:26 »
In der realen Welt hab ich das der Domino Seite in einem budgetierten pitch vorgeschlagen und der Kollege vom Partnerunternehmen war sehr zufrieden damit. Im Sinne von echt total sehr.

Sie werden euch sagen. Hört nicht auf Hassen i Sabbah mit seinen kahlen POX Webservices.

Wir haben SOAP. Das time, life, fortune Monopol mit kübelweise Liebe.
SOAP verwandelt Autobahnen in Bahngleise.
Und Bahngleise in Fahradwege.
Und Fahradwege in Kanäle.
Und Kanäle in Flüsse.
Und Flüsse in Bobbahnen.

Traut denen nicht.   ;)
« Letzte Änderung: 14.03.07 - 16:44:42 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #4 am: 15.03.07 - 19:31:27 »
Um das ein wenig zu relativieren. Wenn sich natürlich eure Organisation zu einem nachhaltigen SOA Ansatz commitet hat und es da auch Leute gibt, die konzeptionell und im technischen Betrieb mit Enterprise Service Bus und so Middleware wirklich umgehen können, dann ists was anderes. Ich kann das nicht und ich behaupte, dass es in vielen Organisationen auch keiner kann.
http://www.theserverside.com/news/thread.tss?thread_id=44639
Nur wenn die Leute dann auf Grund von Marketing-Gewäschen glauben, dass mit der Verteilung wär ja ein Kinderspiel und sowieso dank SOAP transparent, dann ist das einfach nicht wahr.

Wenns einfach nur darum geht ein paar PHP- or whatever Anwendung mit 'ner Notes-DB zu verbinden, ist SOAP unnötiger overkill, der einfach nur verbrannte Arbeit darstellt. Jede selbstrespektierende Web Plattform hat sowas wie jakarta HTTPClient, mit dem man einen HTTP Client quasi emulieren kann, um so Kontakt mit einem Server einer anderen Plattform Kontakt aufzunehmen. SOAP bringt da keine Vorteile.
« Letzte Änderung: 15.03.07 - 19:37:32 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #5 am: 16.03.07 - 06:41:33 »
Als nächstes werde ich mich ein wenig auf den Server Part konzentrieren, der als LotusScript implementiert ist.
Also: Der Agent bekommt die String Darstellung eines xml Dokuments rein und schickt die String Darstellung eines xml-Dokuments raus.
Das in-Dokument wird mit NotesXMLSaxParser geparsed.
Das out-Dokument wird mit NotesXMLDOMParser generiert.
Aber dazu später.
Scheint aber zu funktionieren.
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #6 am: 20.03.07 - 07:04:28 »
Ich hab mir überlegt, das auch der client als Lotus Notes Agent implementiert wird. Das ist realistischer. LS2J bringt ein paar wenige Komplexitäten mit sich, die für das Beispiel nicht nötig sind.
Wenn ihr in der realen Welt den Client für einen Webservice, der z.B. mit einer php Anwendung kommuniziert, dann werdet ihr das am wahrscheinlichsten in einem Agenten machen.

Was soll jetzt der Webservice inhaltlich tun. Stock Quotes wie sonst immer  ??? Nein.  ;D
Ich implementiere das als Math-Service für simple Rechenoperationen mit beliebig vielen Termen (spelling?), Klammern aber ohne Division. Auf vielen Blogs (z.B. bileblog, basicthinking) wird man heute schon mit solchen Fragen als spamschutz konfrontiert.
Z.B.:
Zitat
Berechne [zehn] + [neun](ohne Taschenrechner)
Der business Nutzen des Webservice ist zugegeben nicht sehr hoch, aber als Beispiel sehr brauchbar.
 
Die einzelnen wiederverwendbaren Teile werden so aussehen. Das ist ein highlevel Überblick über die einzelnen Teile des POX Webservice.

ClientServer
1. Client liest Daten aus einem Notes Dokument und erzeugt daraus ein xml Dokument (Java)
2. Client sendet das erzeugte xml Dokument per HTTP an den Server (Java)
3. Server nimmt xml entgegen (LotusScript Agent)
4. Server parst das xml mit der SAX API und erzeugt daraus Datenstruktur für die Weiterverarbeitung (LotusScript)
5. Server verarbeitet die Daten und generiert daraus seinerseits xml, das an den Client zurückgeschickt wird (mit LotusScript print statements)
6. Client parst seinerseits das vom Server zurückgesendete xml mit der SAX Api (Java) und erzeugt daraus aplikationsspezifische Datenstrukturen als Ergebnis
7. Client schreibt das Ergebnis in das Notes Dokument

Das auszutauschende xml wird etwa diese Struktur haben (Beispiel):
client sendet an server:
Code
<?xml version="1.0"?>
<math-in>
	<number parentesis="left">8</number>
	<operator>+</operator>
	<number parentesis="right">2</number>
	<operator>*</operator>
	<number>4</number>
</math-in>

server sendet zurück:
Code
<?xml version="1.0"?>
<math-out>
40
</math-out>
« Letzte Änderung: 20.03.07 - 07:29:04 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #7 am: 21.03.07 - 09:47:20 »
Julian Robichaux sieht es übrigens genau so wie ich:
POX oder REST Webservices sind für eine Menge Fälle die bessere und einfachere Lösung:
http://www.nsftools.com/blog/blog-03-2007.htm#03-11-07 (s. Kommentare).
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #8 am: 24.03.07 - 08:51:23 »
Jeder der in dem Posting [20.03.07 - 07:04:28] beschriebenen Schritte besitzt einen definierten Input und einen definierten Output. Sie sind sehr unabhängig voneinander programmier- und testbar:

Schritt
InputOutput
1. Client erzeugt das zu sendende xml Dokument
Notes Maske, Dokumente etc. xml Dokument als String
2. Client sendet das xml Dokument an den Server
xml Dokument als Stringxml Dokument gepackt in ein HTTP-Post Request auf dem Server
3. Server wandelt das einkommende xml Dokument in einen String um
HTTP Post Request, in dem ein xml-Dokument gepackt istxml Dokument als String
4. Server parst das xml in eine Datenstruktur
xml Dokument als StringDatenstruktur in LotusScript (hier wirds erstmal ein Array aus Types sein)
5. Server macht etwas mit der Datenstruktur (Businesslogik)
Datenstruktur in LotusScricptxml Dokument als String gepackt in eine ausgehenden HTTP-Response
6. Client empfängt zurückgesendete xml Dokument und macht damit etwas (Businesslogik)
xml Dokument Ergebnisse in Client Programm


Die einzelnen Schritte funktionieren unabhängig voneinander. Das ist ein großer Vorteil von Webservices. Die einzelnen Schritte lassen sich in beliebiger Reihenfolge oder sogar paralell entwickeln. Ich fang hier mit Punkt 4 an.
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #9 am: 24.03.07 - 10:35:31 »
Im Agent "poxServer" der unten angehängten Datenbank ist  Punkt "4. Server parst das xml in eine Datenstruktur" mit SAX Parsing implementiert. Als LotusScript. Die SAX-API eignet sich sehr gut, um xml zu lesen. Man kann damit nicht xml schreiben oder editieren. Die SAX-API wurde in sehr vielen Programmiersprachen implementiert. Wenn man SAX-Parsing in LotusScript kann, ist es ein kleiner Schritt das auch in C#, Java, C++, Ruby oder was auch immer zu beherrschen.

SAX ist eine eventgesteuerte API. Man kann sich das so ähnlich vorstellen wie Lotus Notes ein Dokument verarbeitet. Öffnest du ein xml Dokument im Notes Client, dann werden:
Eine Menge Maskenevents aufgerufen (QueryOpen, PostOpen) und die Formeln der einzelnen Felder von links oben nach rechts unten werden berechnet.
So ähnlich verhält es sich mit dem Handler eines xml Parsers.
Es gibt verschiedene Events, die man anmelden kann. Zum Beispiel:
Code
On Event SAX_StartDocument from saxParser Call SAXStartDocument
On Event SAX_StartElement From saxParser Call SAXStartElement
On Event SAX_Characters From saxParser Call SAXCharacters
On Event SAX_EndElement From saxParser Call SAXEndElement
Die komplette Liste findet ihr irgendwo in der Notes Designer Dokumentation.

Im Parsingprozess werden dann die angemeldeten Unterroutinen aufgerufen.
(z.B. Sub SAXEndElement (Source As Notessaxparser, Byval ElementName As String))
Also das ist ein xml Dokument:
Code
<?xml version="1" encoding="UTF-8"?>
<math-in>
	<number parentesis="left">8</number>
	<operator>+</operator>
	<number parentesis="right">2</number>
	<operator>*</operator>
	<number>4</number>
</math-in>
Der SAX Parser geht das von oben bis unten durch und ruft bei definierten "Stellen" angemeldete Subroutinen auf. Er macht das automatisch. Wir müssen nur auf ihn in den angemeldeten Subroutinen reagieren.
 
Mit den oben Beispielhaft angegebenen Events, sieht das so aus:
1. Parsing beginnt-> Ruft Call SAXStartDocument auf.
2. kommt an den öffnenden Tag <math> -> Ruft SAXStartElement auf
3. Kommt an den öffnenden Tag <number> -> Ruft SAXStartElement auf
4. Findet Text zwischen den öffnenden und schliessenden Tags <number> und </number>-> Ruft SAXCharaters auf.
5. Findet den schliessenden Tag </number> -> Ruft SAXSEndElement auf
3. Kommt an den öffnenden Tag <operator> -> Ruft SAXStartElement auf
4. Findet Text zwischen den öffnenden und schliessenden Tags <operator> und </operator>-> Ruft SAXCharaters auf.
5. Findet den schliessenden Tag </operator> -> Ruft SAXSEndElement auf

Und so weiter. Bis zum letzten schliessenden Tag </math>

Nun gibt es z.B. in den <number> tags Attribute. Was ist damit?
<number parentesis="left">
Nun die einzelnen angemeldeten Event-Subroutinen besitzen definierte Parameter.
Zum Beispiel:
Code
Sub SAXStartElement (Source As Notessaxparser,_
	Byval elementname As String, Attributes As NotesSaxAttributeList)
...
End Sub
In jedem Subroutinenaufruf von SAXStartElement wird
a) der Name des Tags als String übergeben (bei <math> wäre das math.
b) die Attribute des Tags als NotesSaxAttributeList übergeben, wobei NotesSaxAttributeList ein einfaches LotusScript Objekt ist. In der angehängten Datenbank könnt ihr euch anschauen wie das genauer verarbeitet wird.

Es ist zugegeben ein bischen gewöhnungsbedürftig, aber zum Lesen von xml Dokumenten ist die SAX Api oft einfacher als die DOM-Api oder traditionelles String-Parsing. Und zwar bedeutend.         

Ich beschreibe jetzt noch ein wenig konkrete Implementierung des Agenten poxParser in der angehängten Datenbank:

Der Agent holt sich von der Funktion getStrMockIn() as String ein XML-Dokument als String zum Testen. Dieser String wird in einen NotesStream geladen (sehr einfach)
Code
Set stream = session.CreateStream
stream.WriteText(strIn)
Dann wird die Funktion
Code
Function xmlProcessIn (streamIn As NotesStream) As Variant
aufgerufen, die das SAXParsing steuert.
Das eigentlich SAXParsing findet dann in
Code
Class MySaxContentHandler
in den Declarations statt.

Ein Objekt dieser Klasse wird von xmlProcessIn erzeugt. Der Konstruktor
Code
Sub new (streamIn As NotesStream)
wird aufgerufen. Dort wird ein saxParser as NotesSAXParser Objekt erzeugt, die events werden angemeldet.
Code
Sub new (streamIn As NotesStream)
		' the data to be retrieved later is saved here
		Redim Preserve mathElem(0)	
		
		
		Set sAXParser = session.CreateSAXParser(streamIn)
		
		' the events to be observed during parsing. calls the subroutines below. 
		
		On Event SAX_StartElement From saxParser Call SAXStartElement
		On Event SAX_Characters From saxParser Call SAXCharacters
		On Event SAX_EndElement From saxParser Call SAXEndElement
		
		On Event SAX_Error From saxParser Call SAXError
		On Event SAX_FatalError From saxParser Call SAXFatalError	
		On Event SAX_Warning From saxParser Call SAXWarning
	End Sub
von xmlProcessIn wird dann als nächstes der ParsingProzess gestartet.

xmlProcessIn:
Code
Set instMySaxContentHandler = New MySaxContentHandler(streamIn) 
instMySaxContentHandler.process

In Class MySaxContentHandler:
Code
Function process () As Variant	
		saxParser.process
	End Function
Die Kontrolle geht nun auf den SAXParser über. Er ruft nun die angemeldeten Event-Funktionen Call SAXStartElement, Call SAXCharacters, etc auf, sobald er während des Parsens von oben nach unten auf ein entsprechendes "Event" "stösst" (z.B. öffnender Tag, Text zwischen öffnenden und schliessenden Tags, schliessender Tag, etc).

In den aufgerufenen Subroutinen wird nun ein Array des ebenfalls in den Declaration definierten Types Math Element erzeugt
Code
Type MathElement 
	name As String
	attribute As String
	value As String
End Type
In der Instanz der Klasse MySaxContentHandler ist dieser Array eine Public Member-Variable:
Code
Class MySaxContentHandler
	Public mathElem() As MathElement
[...]

Hat der SAXParser sämtliche Elemente von oben nach unten durchgearbeitet fällt die Programmkontrolle wieder zurück auf die oben erwähnte Function xmlProcessIn zurück, die den Parsing Prozess angestossen hat. Diese Funktion gibt dann noch die Werte des Arrays mathElem aus.
Code
For i= 1 To Ubound(instMySaxContentHandler.mathElem())
		currentMathElement = instMySaxContentHandler.mathElem(i)
		'Msgbox instMySaxContentHandler.arrValues(i), MB_ICONINFORMATION, instMySaxContentHandler.arrKeys(i) 
		strDebug = strDebug & Chr$(13) & Chr$(10) & |MathElement(| & Cstr(i) & |)-->name="| & currentMathElement.name &_ 
		|" value="| & currentMathElement.value & |" attribute="| & currentMathElement.attribute & |"|
'& |"|
		
	Next
	
	Msgbox strDebug, MB_ICONINFORMATION, "result"

Interessierte sollten einfach den Agenten mal ausprobieren.

Das war Schritt 4:
4. Server parst das xml in eine Datenstruktur   
Input: xml Dokument als String   
Output: Datenstruktur in LotusScript (hier wirds erstmal ein Array eines Types sein)

Nicht für jeden der angesprochenen Schritte muss so viel Code geschrieben werden.
Gruß Axel
« Letzte Änderung: 24.03.07 - 11:08:47 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #10 am: 09.06.07 - 09:15:14 »
Dies wird nun fortgesetzt. Die Zeit zwischen dem letzten Posting in diesem Thread und jetzt umfasst so ziemlich meine schwerste Identitätskrise als Entwickler seit 2003.
Ich wende mich nun Punkt 2 zu: Client (Consumer) sendet das xml Dokument an einen Webservice Server (producer).

Technisch benötigt man das folgende:
Ein HTTP Post Request muss gegen die URL des Webservice producers gesendet werden. Der body des post requests (in webservice lingua: payload) enthält die xml Nachricht, die vom client an den server gesendet wird.

Domino bietet hier erst einmal nativ nichts an. Mir sind aber 2 Wege bekannt:
1. Läuft Domino/Notes auf Microsoft, können bestimmte Microsoft-Com Objekte genutzt werden. Julian Robichaux hat kürzlich zumindest für HTTP GET requests ein Beispiel geliefert.  (http://www.nsftools.com/blog/blog-05-2007.htm#05-10-07)
2. Auch auf der Java Seite hat Julian Robichaux jetzt ein Beispiel gepostet (http://www.nsftools.com/blog/blog-05-2007.htm#05-10-07). Ich werde das auf jeden Fall in meine Erörterungen einbeziehen.

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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #11 am: 09.06.07 - 10:31:47 »
Julians Lösung benutzt keine 3rd party openSource Bibliotheken wie jakarta.commons HTTPClient.
Das mindert natürlich den Aufwand für das Deployment.
Auf der anderen Seite ist das ziemlich low level und das kann leicht dazu führen, dass bestimmte Features nicht unterstützt sind und Fehler drin sind.
Die zentralen Klassen befinden sich in den Scriptlibraries. (Z.B. URLFetcher).
Aus meiner Sicht wird in
Code
public InputStream getUrlAsStream (String urlToGet)
das writer-Objekt nicht korrekt geschlossen.

Code
if (postParams.length() > 0) {
   con.setDoOutput(true);
   OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
   writer.write(postParams);
   writer.flush();
}
Hier müsste nach flush() noch ein close() kommen. So was kann echt in Betrieb zu Problemen führen.

Die Lösung von Julian unterstützt eine Menge Features (basic authentification, ssl, proxies). Ich vermisse unterschiedliche Encoding schemes wie ISO-8859-1 oder UTF-8. In Webservice Projekten kommt es schnell vor, dass man sich damit beschäftigen muß. Aber auch dieser Support liesse sich leicht einbauen. Ich hab mich jedenfalls auf Julians blog höflich zu Wort gemeldet und werde vermutlich selbst eine Alternative bloggen, sobald das hier fertig ist.

Julian bietet die Datenbank als fertige nsf zum Download an.
Einfach auf data-root* eines Dominoserver kopieren. Unterzeichnen, Datei, Extras, Java Debug Console öffnen und den Agenten "Echo Webservice Test (Java)" starten und in Java Debug Console schauen. Dieser Agent benutzt die Skriptbibliothek URLFetcher und spricht den Domino-7-Webservice EchoTest derselben Datenbank an.

Folgendes wird zurückgeliefert:
Als response:
Code
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
 <soapenv:Body>
  <ns1:ECHOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:DefaultNamespace"><ECHOReturn xsi:type="xsd:string">ECHO</ECHOReturn></ns1:ECHOResponse>
 </soapenv:Body>
</soapenv:Envelope>
Als  fetcher.getHeadersReceived():
Code
HTTP HEADERS RECEIVED
HTTP/1.1 200 OK
Server: Lotus-Domino
Date: Sat, 09 Jun 2007 07:58:04 GMT
Content-Type: text/xml; charset=utf-8
Content-Length: 515

Wie man bei response sieht, wird bei Webservices eine Menge "Paketmaterial" geliefert, um eine einfache Information einzupacken.
Inhalt:
Code
ECHO
"Paketmaterial":
Code
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
 <soapenv:Body>
  <ns1:ECHOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:DefaultNamespace"><ECHOReturn xsi:type="xsd:string">  </ECHOReturn></ns1:ECHOResponse>
 </soapenv:Body>
</soapenv:Envelope>

Performance-mässig muss diese ziemlich massive Packetierung nicht schlimm sein. Bei doc/literal Type Webservices steigt der Anteil der Information an der Gesamtnachricht mit dem Umfang der gesendeten Information. In dem Beispiel wird ja einfach nur ein String zurückgeliefert. In der realen Welt werden aber mit Webservices komplexere Datenstrukturen ausgetauscht (größerer Umfang der gesendeten Information).
Ein wirkliches Problem besteht aber darin, dass die Information aus der komplexen Nachricht erst einmal geparsed werden muss. Und dies sollte aus meiner Sicht in einer eigenen Schicht geschehen. In der Java-Welt gibts hierfür fertige Frameworks wie JAXB, die man aber aus meiner Sicht in Domino nicht einsetzen kann. Man kann aber ein eigenes Framework schreiben, das in Folge geschehen soll.

* Der Grund für "in data-root" legen ist einfach, dass die endpointURLs in den Beispielen hartcodiert sind:
Code
String endpoint = "http://localhost/URLFetcher.nsf/EchoTest?OpenWebService"; 
« Letzte Änderung: 09.06.07 - 10:43:17 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #12 am: 09.06.07 - 13:58:40 »
Die Datenbank URLFetcher.nsf hat in der ACL Default als Manager stehen.
Was passiert nun, wenn ich default auf "Kein Zugriff" setze und einen technischen User (hier: admin Axel) auf Managerzugriff?

Auf der Java Console erscheint das hier:
Code
Returning NULL
There was an error: null
java.io.IOException
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:643)
	at UrlFetcher.getUrlAsStream(UrlFetcher.java:389)
	at UrlFetcher.getUrlAsString(UrlFetcher.java:450)
	at JavaAgent.NotesMain(JavaAgent.java:28)
	at lotus.domino.AgentBase.runNotes(Unknown Source)
	at lotus.domino.NotesThread.run(Unknown Source)
Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: http://localhost/URLFetcher.nsf/EchoTest?OpenWebService
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:841)
	at sun.net.www.protocol.http.HttpURLConnection.getHeaderFieldKey(HttpURLConnection.java:1546)
	at UrlFetcher.getUrlAsStream(UrlFetcher.java:375)
	... 4 more
HTTP HEADERS RECEIVED
HTTP/1.1 401 Unauthorized
Server: Lotus-Domino
Date: Sat, 09 Jun 2007 11:17:29 GMT
Connection: close
Expires: Tue, 01 Jan 1980 06:00:00 GMT
Content-Type: text/html; charset=US-ASCII
Content-Length: 146
WWW-Authenticate: Basic realm="/"
Cache-control: no-cache
Der obere Teil zeigt, dass es bzgl. Errorhandling eindeutig Raum für Verbesserungen gibt.
Im Stacktrace findet sich kein Hinweis auf das Problem -> User ist wg. ACL nicht autorisiert.

Die Klasse URLFetcher enthält eine Methode, um mit HTTP Basic Authentification umzugehen.
Nämlich:
Code
 /**
	  * For web sites that require basic authentication, encode the username
	  * and password and add the authentication header. Note that this
	  * method will have to be called again if you call clearHeaders().
	  * Also, if the website uses session-based authentication, you normally
	  * have to add the session header yourself.
	  */
	public void setBasicAuthentication (String username, String password) {
		addHeaderValue("Authorization", 
									createAuthHeader(username, password));
	}
Leider funktioniert das mit Julians code nicht.
Zumindest nicht, wenn ich Notes7 benutze.
Ich bekomme folgenden Fehler:
Code
java.lang.IllegalArgumentException: Illegal character(s) in message header value: BasicQWRtaW4gQXhlbDprZW5ud29ydA==
Eine Erklärung findet sich hier:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4615330
Das von Julian benutzte encodeBuffer hängt offenbar \n characters an und das kann nicht funktionieren.
Auch der Workaround encode durch encodeBuffer in URLFetcher.java zu ersetzen funktioniert nicht.

Ich werde in Folge eine eigene Lösung mit apache.jakarta.HTTPClient schreiben und das Problem melden.

HA. Nun hab ich doch einen Workaround gefunden
URLFetcherJava.createAuthHeader in der SkriptBibliothek muss wie folgt aussehen ->
Code
/**
	  * Helper to base64-encode the authorization strings.
	  */
	private String createAuthHeader (String username, String password) {
		String auth = "";
		
		if (username == null)  {  username = "";  }
		if (password == null)  {  password = "";  }
		
		try {
			sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
			String str = username + ":" + password;
			// patch start
                         auth = "Basic " + encoder.encode(str.getBytes());
			// patch end
		} catch (Exception e) {
		}
		
		return auth;
	}
	
Im Code des Agenten "Echo Web Service Test (Java)" muss die letzte der folgenden Zeilen eingefügt werden, um das nach der ACL Änderung wieder ans laufen zu bringen. Die letzte Zeile ist neu.
Code
public void NotesMain() {

		try {
			// MODIFY: make sure the endpoint is right, and make sure that
			// the local http task is running if you do this on localhost
			String endpoint = "http://localhost/URLFetcher.nsf/EchoTest?OpenWebService";
			UrlFetcher fetcher = new UrlFetcher();
			 fetcher.setBasicAuthentication("Admin Axel", "kennwort") ;
Julians Klasse URLFetcher ist schlauer-weise also so aufgebaut, dass das Feature "Unterstützung von Basic Authentification" durch eine einfache set-Methode eingebunden werden kann.
Und genau das ist "DEPENDENCY INJECTION". Das Object UrlFetcher sucht sich die Information über den User, der für die Autorisierung genutzt nicht selbst. NEIN. Diese Information WIRD VON AUSSEN INJEZIERT. Dependency Injection als Design Pattern hat sich in verschiedenen Objekt Orientierten Sprachen auch über Frameworks wie Spring oder Guice in den letzten Jahren sehr stark verbreitet. Hier haben wir einen Fall von nicht-frameworkgestützter programmatischer Dependency Injection, aber es implementiert das Pattern.
« Letzte Änderung: 09.06.07 - 14:22:47 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #13 am: 14.06.07 - 08:23:12 »
Julian hat meinen Fix-Vorschlag angenommen und will diesen bald in die Datenbank zum Download einarbeiten (Kommentar 9):
http://www.nsftools.com/blog/blog-05-2007.htm#05-22-07
Zitat
Also, thanks very much for the link to the HTTP authentication bug, and your workaround code. Especially the workaround code! It's always the little things that get you. I'll make the change in the download database.

Hey. Das sind Consumer/Client Side Webservice Endpoints  ;D . The Hotness.
Etwas, dass es in Notes offiziell gar nicht gibt.
In der realen Welt kann man damit prima SAP Webservices und eine Menge mehr integrieren.

Ich hab folgende Pläne:
-> Einbau von apache.jakarta.commons.HttpClient als robustere openSource Lösung (bis 24.6.)
-> Demos mit vorhandenen realen Webservices (bis 19.6.)
-> wirklich gutes Errorhandling (bis 28.06.)
-> ein XML-To-Java Binding Framework bis 01.07.)

Gruß Axel
« Letzte Änderung: 14.06.07 - 08:27:56 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #14 am: 01.07.07 - 10:30:40 »
Hier ist nun der einfachste Code mit jakarta.commons HTTP Client. Das macht einfach nur ein HTTP-GET gegen google. Wird noch deutlich weiter ausgearbeitet.
apache.Commons HTTPClient besitzt eine Menge von sinnvoller bis mission critical Zusatzfeatures:
- allgemein konfortabler
- Authentifizierung gegen Proxy
- SSL-Unterstützung
- Unterstützung der HTTP Methoden: GET, HEAD, POST, PUT und DELETE
- einfacher lesender und schreibender Zugriff auf HTTP Bodys
- unterstützt Cookies.
Code
import lotus.domino.*;
import java.io.IOException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;

public class JavaAgent extends AgentBase {

	public void NotesMain() {

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();

		

		} catch(Exception e) {
			e.printStackTrace();
		}
		
		HttpClient client = new HttpClient();
		String url = "http://www.google.com";
		HttpMethod method = new GetMethod(url);
		
		try {
			client.executeMethod(method);
			if (method.getStatusCode() == HttpStatus.SC_OK) {
				String response = method.getResponseBodyAsString();
				System.out.println("response=--------------------\n" + response);
			}
		} catch (HttpException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		} finally {
			method.releaseConnection();
			
		}
	}
}

Etwas komplizierter ist die Einbindung der von jakarta.commons.HTTPClient benötigten Bibliotheken. Man kann die einfach in das lib/ext Verzeichnis der JVM des Notes Clients/Notes Servers packen.
Oder in JavaUserClasses in der Notes-ini. Man kann die auch an den Agenten binden.
Zunächst müssen die benötigten jars sowieso runtergeladen werden. Ich habe festgestellt, dass die 3.01 Version Probleme mit Java 1.4 macht. Offenbar haben die von apache.jakarta beim Kompilieren nicht aufgepasst.  ;D
Deshalb sollte man sich die binary Version der 3.1 rc1 Version herunterladen:
http://jakarta.apache.org/site/downloads/downloads_commons-httpclient.cgi
Die entsprechende jar befindet sich im Root des downloads.
oder EINFACHER aber OHNE DOKU bei maven: http://www.ibiblio.org/maven/commons-httpclient/jars/ (Datei commons-httpclient-3.1-rc1.jar)
Gleichzeitig werden die folgenden beiden jars benötigt:
- commons-codec-1.3.jar (gibts bei maven: http://www.ibiblio.org/maven/commons-codec/jars/)
- commons-logging-1.3.jar (gibts bei maven: http://www.ibiblio.org/maven/commons-logging/jars/)

Alle diese jars müssen jetzt in ein und dasselbe Verzeichnis kopiert werden.
Dann kann über die Schaltfläche Projekt bearbeiten in der Notes Designersicht des Agenten eine Dialogbox geöffnet werden, mit der diese jars hinzugefügt werden können (s. Screenshot).

Dies ist der Schlüssel, Domino als Webservice Client zu verwenden. Ok. Die WS-* Specs kriegt man so auch nicht unterstützt, aber die sind eh noch in Arbeit. Ansonsten kann man damit aber von SOAP-Zugriffen auf SAP bis rebellischen REST Webservices in Domino alles als Client verarbeiten. Ich werde das noch weiter ausführen. 

Gruß Axel

« Letzte Änderung: 01.07.07 - 14:05:15 von Axel Janssen »
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

Offline flaite

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.966
    • mein del.icio.us
Re: wann brauchen wir SOAP Webservices und wann nicht?
« Antwort #15 am: 01.07.07 - 10:37:13 »
SOAP ist für viele Aufgaben ziemlich umstritten. Es gilt als für die meisten Aufgaben zu komplex. Viele große Organisationen, die Webservices anbieten wie Amazon, del.icio.us, yahoo, google, etc. haben von SOAP inzwischen Abstand genommen und bieten nicht-SOAP Webservices an. Stichworte sind REST-Webservices oder POX (Plain Old XML) Webservices. Mittlerweile gibts von Leonard Richardson und Sam Ruby (imho ein IBM Mitarbeiter) ein O'Reilly Buch, das das alles ein bischen ordnet. Der Name ist "RESTfull Webservices". Sehr gut geschrieben und mit einer Menge Beispielen (meist in Ruby).
 
« Letzte Änderung: 01.07.07 - 13:16:21 von Axel Janssen »
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