Work in Progress
Diese Seite ist aktuell im Review! Die Seite wurde noch nicht qualitätsgesichert und kann Fehler enthalten.
Die verlinkten Seiten sind ggf. nur für Schleupen-Mitarbeiter sichtbar.

Lean Communication Framework (LCF)

Das Lean Communication Framework (LCF) stellt eine leichtgewichtige Technologie dar, um AFw-Code möglichst einfach von CS 3.0 aus anbinden zu können. Die Grundidee hierbei ist, insbesondere aus Nutzersicht möglichst ähnlich wie mit der WCF arbeiten zu können - es handelt sich allerdings um eine alternative Technologie.

Design

Es muss eine Spezifikation durch eine WSDL zwischen Server und Client existieren!

Ein Beispiel dieser Schnittstelle ist wie folgt dargestellt:

Die Signatur einer Schnittstelle hat im Standard zwei Operationen:

  • Execute()
    Die Ausführung der eigentlichen Operation, die prinzipiell asynchron ausgeführt wird. Der ExecuteResponse ist dementsprechend leer.
  • GetReply()
    Diese Operation dient dem Auslesen der eigentlichen Antwort. Das Muster ist also ähnlich dem Request-/Reply-Muster mit dem Unterschied, dass die Bindung über eine Event im Workflow erfolgt.

Die Verwendung einer WSDL als zentrale Schnittstelle hat folgende Vorteile:

  • Diese Schnittstelle kann und sollte im kanonischen Servicemodell modelliert werden. Daher liegt dann eine allgemeine Dokumentation automatisch vor.
  • Mit Hilfe der DevelopmentTools ist dann automatisch eine Kompatibilitätsprüfung vorhanden (siehe u.a. Kompatibilität von Services).
  • Der C#-Code der zu verwendenden Typen kann mit Sigento einfach generiert werden.

Die LeanAction, also der auszuführende CFw-/AFw-Code, wird über einen CFw- oder AFw-Job angebunden. Dieser kann dann die entsprechenden 'Request' (vgl. 3.0: Operationsvertrag (OperationContract)) zur weiteren Verarbeitung auslesen. Intern werden DB-Tabellen als Transfertabellen verwendet, was für den Nutzer allerdings vollständig gekapselt wird. Um hier möglichst wenig implementieren zu müssen, werden entsprechend Hilfsklassen etc. zur Verfügung gestellt. Wie diese angeschlossen werden können, wird im Folgenden aufgezeigt.

Eine Benachrichtigung der Fertigstellung von LeanActions erfolgt durch Aufruf von Events gegen CS 3.0. Hier liest ein CS 3.0 ScheduledService die Transferdaten aus und löst das allgemeine Event ILeanResponseReceivedEventService oder ILeanFaultReceivedEventService aus, so dass im Workflow der nächsten Schritt betreten wird. Dann können die Daten über die Methode GetReply() abgeholt werden.

Mit der LCF kann als weiterer Anwendungsfall ebenfalls CS 3.0-Events aus CFw / AFw-Code heraus ausgelöst werden. Hierzu muss eine CS 3.0-Event-Schnittstelle spezifiziert sein und in CS 1.0/2.0 hierfür ein Event an LCF übergeben werden.

Anwendungsszenarien
Anbindung von CS 2.0-Code

Das LCF hat das Ziel, insbesondere Code des AFw auszuführen. Da dieser nicht als WCF-Service auskodiert werden kann, erfolgt die Anbindung über das CS 2.0-Jobsystem. Analog können langlaufende Operationen ausgelagert werden.

Das 'Lean Communication Framework' sollte möglichst nicht verwendet werden, wenn WCF-Aufrufe möglich sind. Es dient lediglich dazu, um

  • AFw-Code für ActivityServices (hier bei der Implementierung Technologieneutral als 'LeanAction' benannt) auszuführen
  • Langlaufende Operationen im CFw-/AFw-Kontext auszuführen. Dies sollte aber möglichst vermieden werden - sondern hier sollte eine Lösung geschaffen werden, die besser skaliert und zyklisch 'kleinere' Serviceoperationen ausführt
Anbindung von CS 1.0-Code

Möglichst analog zu Anbindung von CS 2.0-Code.

Eventauslösung von CS 2.0/CS1.0 aus

Generell besteht die Möglichkeit, von CS 1.0/2.0, einen allgemeinen Request abzulegen, um damit dann ein CS 3.0-Event auszulösen.

Einbettung in die Gesamtarchitektur

Generell sollte dieses Framework vermieden werden und besser WCF verwendet werden!

Falls es dennoch verwendet wird, gibt es folgende Schlussfolgerungen:

  • Es folgt, dass Serviceoperationen, die rein lesend arbeiten (vgl. 1.2: QueryService (QueryService, Declaration) etc.), per CFw-Technologie als WCF-Webservice zu implementieren sind, um damit eine besser skalierende und performantere Lösung zu erhalten.
  • Entsprechend sollte ein Event Richtung Geschäftsprozess ausgelöst werden, um die Fertigstellung der LeanAction zu signalisieren (siehe 1.2: EventService (EventService, Declaration)) aufgerufen werden.
  • Empfehlung: Ein Job pro CS 2.0-Applikation.
  • Die Implementierung des Jobs kann als Einzelaktion oder als Massenaktion ausgeführt werden (siehe oben). Empfehlung: Anbindung als Einzelaktion.
  • Die Event-Service-Schnittstelle ist durch das CS 3.0-Land auszuliefern.
  • Die ServiceImplementationGroup Schleupen.CS.iMSB sollte nur Mandant Knoten zugewiesen werden. Sonst kann keine 1-1 Bezeihung von CS2.0 Mandant zur CS3.0 Systemstrukturelement für den auslösen des Events hergestellt werden.
Funktionsweise

Im Folgenden wird das Design genauer dargestellt.

Design Request-Reply
  • Für Anbindung aus CS 3.0 gibt es die API Schnittstelle ILeanActionGateway, wobei die Implementierung wie gewohnt durch den DI-Container aufgelöst wird.
  • Die Methode Exceute() in LeanActionGateway schreibt in die CS 2.0-Tabelle namens sy3leanactionrequest die eingehenden Requests. Die Requests werden hier serialisiert abgelegt.
  • Ab S19 statt direkt in der CS 2.0-Tabelle zu schreiben, wird über DeferredEvents einen LeanActionExecutionRequestedEventService Event ausgelöst. Der Event wird abonniert und die Request in der CS 2.0-Tabelle geschrieben.
  • Grund ist die Vermeidung von verteilten Transkationen.
  • Wenn Exceute() mit einen JobCategoryShortcut (Kürzel der Jobkategorie von CS 2.0) aufgerufen worden ist, wird anschließend der CS 2.0-Job für diesen Request per WCF-Aufruf gestartet. Alternativ kann ein CS 2.0-Job so konfiguriert werden, dass es zyklisch läuft und alle relevante Requests verarbeitet.
  • Für CS 2.0 Anbindung gibt es die API Klassen LeanActionRequestReader und LeanActionReplyWriter
  • Über die LeanActionRequestReader kann der eingehende Request gelesen und deserialisiert werden. Hierzu gibt es die Option, alle Requests für einen bestimmten ServiceImplementation zu lesen, oder der Request für einen bestimmten RequestId
  • Über die LeanActionReplyWriter kann einen ausgehende Reply in eine CS 2.0 Tabelle namens sy3leanactionresponse geschrieben werden. Der Reply (entweder im positiven Fall ein Response oder im Fehlerfall ein Fault) werden hier serialisiert abgelegt. Zusätzlich wird in die CS 2.0-Tabelle namens sy3leanevent einen LeanResponseReceivedEvent oder ein LeanFaultReceivedEvent geschrieben.
  • Der CS 3.0-ScheuledService Schleupen.CS.SY.IOP.LeanCommunication.LeanEvents.ScheduledForwardLeanEventsActivityService liest die Einträge aus der Tabelle namens sy3leanevent und löst pro Eintrag der Event aus.
  • In CS3.0 wird mit Hilfe der Methode LeanActionGateway.GetReply() der Reply gelesen. Beim Fault wird hierbei eine FaultException geworfen.

Wenn in einen Service-Aufruf GetReply und zusätzlich ein CS 3.0 Repository verwendet wird, kann es zu einer verteilten Transaktion kommen

Design Eventsauslösung
  • Für CS 2.0 Server Anbindung gibt es die API Klasse LeanEventWriter
  • Über die LeanEventWriter kann der Event-Request serialisiert abgelegt.
  • Einen Event-Request kann entweder für einen LeanActionRequest (statt einen LeanActionReply) oder für einen CS2.0 Mandant ausgelöst werden.
  • Für CS 2.0 Client Anbindung gibt es eine API Klasse LeanEventWriter, die von der IOP-Exporte ($/CS3/CS2/Basis/CS.SY.IOP/Export/CS.SY.IOP/LCF) ins Projekt verlinkt werden muss
  • Zusätzlich muss Schleupen.CS.SY.IOP.LeanCommunication.LeanCommunicationService_1.0.wsdl von der IOP-Exporte ins Projekt verlinkt und Sigento angeschlossen
  • Über die LeanEventWriter wird Event-Request serialisiert und über der IOP-LeanCommunicationService abgelegt.
  • Einen Event-Request wird für einen CS2.0 Mandant, der über den SessionXml ermittelt wird, augelöst werden.
  • Der CS 3.0-ScheuledService Schleupen.CS.SY.IOP.LeanCommunication.LeanEvents.ScheduledForwardLeanEventsActivityService liest die Einträge aus der Tabelle namens sy3leanevent. Pro Eintrag wird der Event-Request serialisiert, die SessionTokenHeader gesetzt und über dem BusinessEventPublishingService das Event ausgelöst.
  • Der CS 3.0-ScheuledService sollte nur auf Mandant Knoten laufen. Der ScheuledService liest dann alle Einträge für sein einige ElementId/SystemUsageId plus alle Einträge für die gemappten Mandanten. Für alle Einträge ohne ElementId/SystemUsageId gilt: diese werden an dem konfigurierten Knoten nur dann zugestellt, wenn der Mandant in der gesamten Konfiguration nur einmal enthalten ist oder der Konfigurationseintrag mit IsFallback = true versehen ist.
    • Besteht die Möglichkeit, dass das Event in einem integrierten System ausgelöst wird, dürfen die Angaben ElementId/SystemUsageId im Event nicht fehlen, da ansonsten die korrekte Zustellung nicht gewährleistet ist!
Monitoring

Falls ein Eintrag in der Datenbanktabelle sy3leanactionrequest oder sy3leanevent älter als der konfigurierte Wert ist, wird eine Aufgabe erstellt.

Es gibt im GP its.sms eine UI zur Überwachung der Datenbanktabellen. Die Aufgabe enthält einen Link zu diesem UI. Falls ein Eintrag älter als der konfigurierte Wert ist, wird der Eintrag in der Oberfläche visuell hervorgehoben.

Der vorkonfigurierte Wert ist defaultmässig 24 Stunden. Der Wert kann wie folgt geändert werden (Beispiel 12 Stunden):

$sessionToken = Request-SystemSessionToken
Set-Int32ConfigurationValue -SessionToken $sessionToken -ArtifactIdentifier Schleupen.CS.SY.IOP.LeanCommunication.HoursUntilOverdueWarning_1.0 -Scope Global -Value 12

Implementierung

Request-Reply

Um das LCF zu nutzen, müssen grob folgende Dinge getan werden:

  1. Aufruf der Methode Execute eines einer Instanz der Klasse LeanActionGateway
  2. Definition eines CS 1.0/CS2.0-Jobs
  3. Lesen des / der zu verarbeitenden Request(s) und Ausführen der eigentlichen Aktion in CS 2.0/ 1.0
  4. [optional] Schreiben der Response-Message in die Transfertabelle mit Hilfe des LCF
  5. [optional] Lesen der Response-Message in CS 3.0 mit Hilfe des LCF
Anbindung im CS 3.0 Client
  • Nuget-Paket einbinden
    Schleupen.CS.SY.IOP.LCF.Client oder Schleupen.CS.SY.IOP.LCF.Client.NHibernate51
  • Der Windsor Container für den Schleupen.CS.SY.IOP.LCF.Client ist zu konfigurieren. Hier zu wird auch der ServiceBusClient benötigt
public class ServiceHostFactoryConfigurator : WcfContainerConfigurator
{
    // ...

    protected override void OnContainerConfigured(IWindsorContainer windsorContainer)
    {
        if (windsorContainer == null) { throw new ArgumentNull(nameof(windsorContainer)); }

        windsorContainer.Install(new ServiceBusClientInstaller(IsInsideWcfOperation));
        windsorContainer.Install(new LeanCommunicationFrameworkInstaller(IsInsideWcfOperation));
        // ...

        base.OnContainerConfigured(windsorContainer);
    }
}
  • Ab S19 werden DeferredEvents verwendet, um der Request ohne verteiltes Transaktion der in CS 2.0 Datenbank zu schreiben. Dafür muss das Land die Datenbankpatch für DeferredEvents bereitstellen: Datenbankpatch für DeferredEvents.
  • Ausführung der CS 2.0 Job als Einzel-Aktion. Hier wird der Request geschrieben und den CS 2.0 Job gestartet.
ExecuteRequest request = new ExecuteRequest();
request.CorrelationId = ...

LeanActionRequestId leanActionRequestId = new LeanActionRequestId(request.CorrelationId);
LeanActionGateway gateway = new  LeanActionGateway();
gateway.Exceute<ISomeInterface, SomeRequest>(leanActionRequestId, request, "JobCategoryShortcut");
  • Ausführung der CS 2.0 als Massenaktion. Hier wird der Request geschrieben. CS 2.0 Job wird nicht gestartet.
ExecuteRequest request = new ExecuteRequest();
request.CorrelationId = ...

LeanActionRequestId leanActionRequestId = new LeanActionRequestId(request.CorrelationId);
LeanActionGateway gateway = new  LeanActionGateway();
gateway.Exceute<ISomeInterface, SomeRequest>(leanActionRequestId, request);
  • (Standard LCF) Events abonnieren, um mitzubekommen, dass das Ergebnis abholbereit ist:
    • Schleupen.CS.SY.IOP.LeanCommunication.LeanActions.LeanResponseReceivedEventService_3.0
    • Schleupen.CS.SY.IOP.LeanCommunication.LeanActions.LeanFaultReceivedEventService_3.0
  • Abholen der Nutzdaten
    • Wenn in einen Service-Aufruf GetReply() und zusätzlich ein CS 3.0 Repository verwendet wird, kann es zu einer verteilten Transaktion kommen
LeanActionRequestId leanActionRequestId = new LeanActionRequestId(request.CorrelationId);
LeanActionGateway gateway = new  LeanActionGateway();
GetReplyResponse response = gateway.GetReply<ISomeInterface, GetReplyResponse>(leanActionRequestId);
Implementierung des "Service" als Einzel-Aktion (CS 2.0)
  • CS 2.0-Job wie bisher anlegen
    • Name Jobparameter: LeanActionRequestId
    • Name Jobparameter: ServiceInterfaceId - nur informell
  • Ein Job pro Service
// JobParameter für die Id des LeanAction-Request auslesen.

string leanActionRequestIdString = status.GetParameterString("LeanActionRequestId");
string serviceInterfaceId = status.GetParameterString("ServiceInterfaceId");
LeanActionRequestId leanActionRequestId = new LeanActionRequestId(Guid.Parse(leanActionRequestIdString));

using (LeanActionRequestReader requestReader = new LeanActionRequestReader())
{
    KeyValuePair<LeanActionRequestId, ExecuteRequest> executeRequest = 
        requestReader.ReadLeanActionRequest<ExecuteRequest>(leanActionRequestId);
     
    // Assemble request
}
Implementierung des "Service" als Massenaktion (CS 2.0)
  • CS 2.0-Job wie bisher anlegen
  • Ein Job pro Applikation
using (LeanActionRequestReader requestReader = new LeanActionRequestReader())
{
    IEnumerable<KeyValuePair<LeanActionRequestId, ExecuteRequest>> result =
                requestReader.ReadAllLeanActionRequest<ISendLcfTestRequestActivityService, ExecuteRequest>();

    // Assemble requests
}
Ergebnis des "Service" zurückgeben (CS 2.0)
  • Response als Reply an CS 3.0 zurückgeben (hier wird auch das LeanResponseReceivedEvent ausgelöst)
LeanActionReplyWriter replyWriter = new LeanActionReplyWriter(); 
GetReplyResponse replyResponse = new GetReplyResponse(leanActionRequestId.Value);
replyWriter.InvokeResponseAsReplyToLeanActionRequest<ISendLcfTestRequestActivityService, GetReplyResponse>(
  leanActionRequestId, replyResponse);
  • Fault als Reply an CS 3.0 zurückgeben (hier wird auch das LeanFaultReceivedEvent ausgelöst)
FaultException faultException = new FaultException<UnhandledFaultContract>(new UnhandledFaultContract
{
    Id = leanActionRequestId.Value.ToString()
});
replyWriter.InvokeFaultAsReplyToLeanActionRequest<ISendLcfTestRequestActivityService>(leanActionRequestId, faultException);
  • Nur Event auslösen, ohne Reply
LeanEventWriter eventWriter = new LeanEventWriter();
RaisedNotification eventRequest = new RaisedNotification()
{
	CorrelationId = leanActionRequestId.Value.ToString()
};

eventWriter.InvokeEvent<ISomethingHappendEventService, RaisedNotification>(eventRequest, leanActionRequestId);
Event-Auslösung

Um CS 3.0-Events über das LCF auszulösen, müssen grob folgende Dinge getan werden

  1. CS 3.0-Schnittstelle designen und über das zugehörige CS 3.0-Land deployen
  2. In CS 2.0 die Methode InvokeEvent() einer Instanz der Klasse LeanEventWriter aufrufen
CS 2.0 Anschluss zur Auslösung der CS 3.0-Events (im Server)

API für CS 2.0-Server steht in scsyiop_ALParts.LCF.dll zu Verfügung. (Export unter $/CS3/CS2/Basis/CS.SY.IOP/Export/CS.SY.IOP/Win32).

Hier muss der Mandant für das automatische Interop Mapping angegeben werden.

RaisedNotification eventRequest = new RaisedNotification()
{
    CorrelationId = Guid.NewGuid();
};

LeanEventWriter eventWriter = new LeanEventWriter();
eventWriter.InvokeEvent<ISomethingHappendEventService, RaisedNotification>(eventRequest, Session.Current.GetMandant());

Bei allen Events die auf der CS 3.0 Seite nicht im Netzmandanten ausgelöst werden sollen, ist entsprechend die ElementId der Systemstruktur anzugeben

RaisedNotification eventRequest = new RaisedNotification()
{
    CorrelationId = Guid.NewGuid();
};

Guid elementId = Guid.Empty; // ermitteln nach fachlichen Kriterien
Guid systemUsageId = Guid.Empty; // ermitteln nach fachlichen Kriterien
SystemStructureReference elementReference = new SystemStructureReference(elementId, systemUsageId);

LeanEventWriter eventWriter = new LeanEventWriter();
eventWriter.InvokeEvent<ISomethingHappendEventService, RaisedNotification>(eventRequest, elementReference);
CS 2.0 Anschluss zur Auslösung der CS 3.0-Events (im Client)

API für CS 2.0-Client importieren:

  • LeanEventWriter.cs und Schleupen.CS.SY.IOP.LeanCommunication.LeanCommunicationService_1.0.wsdl von IOP-Export ($/CS3/CS2/Basis/CS.SY.IOP/Export/CS.SY.IOP/LCF) ins Projekt verlinken.
  • Sigento als Benutzerdefiniertes Tool für der WSDL konfigurien
  • Hinter diesen API, findet einen Server-Aufruf statt.
RaisedNotification eventRequest = new RaisedNotification()
{
    CorrelationId = Guid.NewGuid();
};

LeanEventWriter eventWriter = new LeanEventWriter();
eventWriter.InvokeEvent<ISomethingHappendEventService, RaisedNotification>(eventRequest);

Bei allen Events die auf der CS 3.0 Seite nicht im Netzmandanten ausgelöst werden sollen, ist entsprechend die ElementId der Systemstruktur anzugeben

RaisedNotification eventRequest = new RaisedNotification()
{
    CorrelationId = Guid.NewGuid();
};

Guid elementId = Guid.Empty; // ermitteln nach fachlichen Kriterien
Guid systemUsageId = Guid.Empty; // ermitteln nach fachlichen Kriterien
SystemStructureReference elementReference = new SystemStructureReference(elementId, systemUsageId);

LeanEventWriter eventWriter = new LeanEventWriter();
eventWriter.InvokeEvent<ISomethingHappendEventService, RaisedNotification>(eventRequest, elementReference);

Abgrenzung

Keine Auslösung von beliebigen Events.

Stärken und Schwächen

Stärken
  • relativ einfache Anbindung im Gegensatz zu SI
Schwächen
  • proprietäre Technologie
Cookie Consent mit Real Cookie Banner