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.

Zugriff auf Konfigurationen

Dieses Muster beschreibt, wie Konfigurationswerte aus der Konfigurationsverwaltung gelesen bzw. geschrieben werden können.

Design

Das Muster wird als Domänenklasse für einen Konfigurationswert für den Zugriff auf die Konfigurationsverwaltung Schleupen.CS.PI.AIF.Configuration implementiert.

Implementierung

Zur Speicherung eines Konfigurationswertes muss ein neuer Domänentyp definiert werden, der zur Speicherung und zur Definition der Metadaten verwendet wird. Dieser Typ muss entweder durch den DataContract- oder den Xml-Serializer serialisierbar sein.

Es wird empfohlen, den XmlSerializer zu verwenden (via Attributierung), da dieser auch bei unterschiedlicher Reihenfolge der Eigenschaften eine korrekte Deserialisierung ermöglicht.

Bei Verwendung des DataContractSerializer muss auf die korrekte Reihenfolge der Eigenschaften geachtet oder durch OrderAttribute festgelegt werden. Bei Verwendung der Powershell zur Speicherung eines Wertes muss der Benutzer diese Reihenfolge kennen und beachten, da ansonsten Werte bei der Deserialisierung verloren gehen.

Weiterhin muss dieser Typ die Schnittstelle IConfigurationValueV2 aus Schleupen.CS.PI.AIF.Configuration implementieren. Diese Schnittstelle ermöglicht den Zugriff auf einen ConfigurationArtifactIdentifier, der zur eindeutigen Identifizierung des Konfigurationswertes über das Objekt dient.

Verwendung der Konfigurationsverwaltung

Der Zugriff auf die Konfigurationsverwaltung sollte innerhalb eines Controllers erfolgen, da hierdurch Serviceaufrufe erfolgen. Per Dependency Injection wird dem Controller ein Objekt des Typs Schleupen.CS.PI.AIF.Configuration.Configuration injiziert. Dazu muss dem Konstruktor ein Parameter hinzugefügt werden, dessen Typ die Schnittstelle Schleupen.CS.PI.AIF.Configuration.IConfigurationV2 implementiert.

internal sealed class BuecherAusleihenController : IBuecherAusleihenController
{
    private readonly IConfigurationV2 configuration;

    public BuecherAusleihenController(..., IConfigurationV2 configuration)
    {
        if (configuration == null) { throw ExceptionBuilder.ArgumentNull(() => configuration); }
        // ...
        this.configuration = configuration;
    }

    public void VerlaengereAusleihfrist(string benutzerSid)
    {
        if (string.IsNullOrWhiteSpace(benutzerSid)) { throw ExceptionBuilder.ArgumentNull(() => benutzerSid); }

        Benutzerkonto benutzerkonto = benutzerkontoRepository.QueryBySid(benutzerSid);
        try
        {
            AusleiheConfigurationValue ausleiheConfigurationValue = configuration.Read<AusleiheConfigurationValue>();
            TimeSpan verlaengerungsDauer = benutzerkonto.VerlaengereAusleihFrist(ausleiheConfigurationValue);
            // ...
        }
    }

    // ...
}

Konfigurationswerte können mit einer Gültigkeit versehen werden (siehe unten). In diesem Fall werden zur Zeit ungültige Werte beim Lesen durch die Configuration nicht zurückgeliefert.

Anlegen eines neuen Konfigurationswertes per PowerShell

Das Anlegen eines neuen Konfigurationswertes kann über die Client-API wie oben oder per Powershell erfolgen. Im folgenden wird das Anlegen eines Konfigurationswertes per Powershell beschrieben.

Dazu wird zunächst ein Xml-Dokument per Powershell erzeugt. Dieses Xml-Dokument repräsentiert die serialisierte Version der Klasse AusleiheConfigurationValue die weiter oben aufgeführt ist.

$xmlDoc = New-Object System.Xml.XmlDocument
 
$root = $xmlDoc.CreateElement("AusleiheConfigurationValue")
$xmlDoc.AppendChild($root)
 
$element = $xmlDoc.CreateElement("MaxAusleiheTage")
$root.AppendChild($element)
 
$value = $xmlDoc.CreateTextNode("25")
$element.AppendChild($value)

Anschließend kann das erzeugte Xml-Dokument mit dem Befehl Set-ConfigurationValue wie folgt gespeichert werden.

$sessionToken = Request-SessionToken -ViewName "Standard" -ElementTypeName "Mandant" -ElementName "9999"
 
Set-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Document $xmlDoc

Alternativ kann ein Xml-Dokument als String übergeben werden:

Set-ConfigurationValue -SessionToken $sessionToken -ArtifactIdentifier "Schleupen.CS.MT.BIB.Ausleihen.Ausleihekonfiguration_1.0" -Scope User -ScopeValue "User SID" -Document "<AusleiheConfigurationValue><MaxAusleiheTage>25</MaxAusleiheTage></AusleiheConfigurationValue>

Es kann zu jeder eindeutigen Kombination (Scope, ScopeValue) ein Konfigurationswert gespeichert werden. Die Auswertereihenfolge ist weiter unter beschrieben.

Optional kann ValidFrom- & ValidTo-Werte angegeben werden. Diese werden nur eine Auswirkung haben, wenn der Konfigurationswert die Schnittstelle ITimeBoxedValue implementiert.

  • Falls die Schnittstelle ITimeBoxedValue implementiert wird, und der Wert ValidFrom nicht definiert ist, wird den aktuellen Datum beim Anlegen verwendet.
  • Falls die Schnittstelle ITimeBoxedValue implementiert wird, und der Wert ValidTo nicht definiert ist, wird null verwendet.
Set-ConfigurationValue -SessionToken $sessionToken -ArtifactIdentifier "Schleupen.CS.MT.BIB.Ausleihen.Ausleihekonfiguration_1.0" -ValidFrom (Get-Date "08.05.2015 08:00")  -ValidTo (Get-Date "08.05.2015 10:00")  -Scope User -ScopeValue "User SID" -Document $xmlDoc
Vereinfachter Zugriff für primitive Datentypen
$sessionToken = Request-SessionToken -ViewName "Standard" -ElementTypeName "Mandant" -ElementName "9999"
$timespan = New-TimeSpan -Days 1 -Hours 2 -Minutes 3 -Seconds 4
$date = get-Date
 
Set-BooleanConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "BooleanValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value $true
Set-StringConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "StringValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value "Test von Stringvalues."
Set-Int32ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "Int32ValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value 2147483647
Set-Int64ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "Int64ValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value 9223372036854775807
Set-DecimalConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "DecimalValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value 123.456
Set-TimeSpanConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "TimeSpanValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value $timespan
Set-DateTimeOffsetConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.AIF.Configuration" -Name "DateTimeOffsetValueTest" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID" -Value $dat
CustomDataTypes als Datentyp für eine Konfiguration verwenden

Ab CS.PI 3.9 können auch CustomDataTypes als Datentyp für eine Konfiguration verwendet werden.

Hierzu muss zunächst über den MetadataActivityService die um den CustomDataType erweiterte WSDL des ManageCdtConfigurationActivitySerivce abgerufen werden:

http://localhost/Schleupen/Service%20Bus/Broker/MetadataActivityService.svc/CdtConfiguration/Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService_3.1?parameter=Schleupen.CS.MT.BIB.Buecher.BuchVerlustAbwickelnTask_3.1

CdtConfiguration ist der Name des Broker - Plugin, welches die WSDL erweitert. Als Parameter muss die ArtifaktId des CustomDataTypes angegeben werden.

Diese WSDL kann, analog zu anderen WSDLs, in das Visual Studio Projekt eingebunden und mit Sigento generiert werden:

Danach kann nach dem Muster Gateway zu entfernten Objekten ein Gateway implementiert werden:

internal class BuchVerlustAbwickerlnTaskConfigurationGateway
    : IBuchVerlustAbwickerlnTaskConfigurationGateway
{
    private readonly IManageCdtConfigurationActivityServiceClientFactory clientFactory;
    private readonly ISessionTokenProvider sessionTokenProvider;

    private readonly ArtifactIdentifierContract artifactIdentifier = new ArtifactIdentifierContract()
    {
        Namespace = "Schleupen.CS.MT.BIB",
        Name = "Test",
        ExternalVersion = "3.1"
    };

    public BuchVerlustAbwickerlnTaskConfigurationGateway(
        IManageCdtConfigurationActivityServiceClientFactory clientFactory,
        ISessionTokenProvider sessionTokenProvider)
    {
        this.clientFactory = clientFactory;
        this.sessionTokenProvider = sessionTokenProvider;
    }

    public void Write(BuchVerlustAbwickelnTaskContract buchVerlustAbwickelnTaskContract)
    {
        using (IManageCdtConfigurationActivityServiceClient client = clientFactory.Create())
        {
            try
            {
                client.Write(
                    new WriteRequest(
                        sessionTokenProvider.Token,
                        buchVerlustAbwickelnTaskContract,
                        artifactIdentifier,
                        new QualifiedScopeContract() { Scope = ScopeContract.Global },
                        null,
                        null));
            }
            finally
            {
                client.CloseSafely();
            }
        }
    }

    public BuchVerlustAbwickelnTaskContract Read()
    {

        using (IManageCdtConfigurationActivityServiceClient client = clientFactory.Create())
        {
            try
            {
                var response =
                    client.Read(
                        new ReadRequest(
                            sessionTokenProvider.Token,
                            artifactIdentifier,
                            new QualifiedScopeContract() { Scope = ScopeContract.Global },
                            null));

                return response.Data;
            }
            finally
            {
                client.CloseSafely();
            }
        }
    }
}
Standardkonfiguration über eine Konfigurationskript vorgeben

Im Konfigurationsskript kann eine Standardkonfiguration wie folgt angelegt werden:

$client = Get-ServiceClient -ServiceIdPrefix "CdtConfiguration" -ServiceId "Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService_3.1" -Parameter "Schleupen.CS.MT.BIB.Buecher.BuchVerlustAbwickelnTask_3.1"
 
$sessionTokens = Request-SessionToken -DatabaseSchemaName "BIB"
 
foreach ($sessionToken in $sessionTokens) {
 
    $request = New-Object "Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService.V3_1.WriteRequest"
    $request.SessionToken = $sessionToken
    $request.Name  = New-Object "Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService.V3_1.ArtifactIdentifierContract"
    $request.Name.Namespace = "Schleupen.CS.MT.BIB"
    $request.Name.Name = "Test"
    $request.Name.ExternalVersion = "3.1"
 
    $request.QualifiedScope = New-Object "Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService.V3_1.QualifiedScopeContract"
    $request.QualifiedScope.Scope = [Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService.V3_1.ScopeContract]::Global
 
    $request.Data = New-Object "Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService.V3_1.BuchVerlustAbwickelnTaskContract"
    $request.Data.BuchTitel = "CleanCode"
    $request.Data.ZuletztAusgeliehenAn = New-Object "Schleupen.CS.PI.AIF.Configuration.ManageCdtConfigurationActivityService.V3_1.BenutzerContract" 
    $request.Data.ZuletztAusgeliehenAn.Sid = "S-1-1-0"
    $request.Data.ZuletztAusgeliehenAn.Name = "Jeder"
 
    $client.Write($request);
}
Pflichtfelder, Beschreibung, Anschluss des Datenänderungsprotokolls

Bei Verwendung des Cmdlets innerhalb eines Konfigurationsskriptes ist sicherzustellen, dass der ausführende Benutzer der Installation, das Funktionsrecht Schleupen.CS.apl.kvw.svk.Verwalten gewährt wurde.
Ansonsten lässt sicht das Skript nicht ausführen und die Installation scheitert!

Es ist möglich, dass Änderungen an Konfigurationswerten in das Datenänderungsprotokoll geschrieben werden.

Dazu muss ein passender Konfigurationstyp auf dem Element, wo auch die Konfigurationswerte existieren, erstellt werden. In diesem Beispiel ist dies das Systemelement:

New-ConfigurationType -ArtifactIdentifier Schleupen.CS.PI.Test_1.0 -WriteChangeLog -SessionToken (Request-SystemSessionToken)

Nun werden Änderungen an Werten, die denselben ArtifactIdentifier haben, in das Datenänderungsprotokoll geschrieben.

Set-ConfigurationValue -ArtifactIdentifier Schleupen.CS.PI.SBE_1.0 -Scope Global -Document "<Foo/>"  -SessionToken (Request-SystemSessionToken)

Bei komplexen Datentypen wird das gesamte XML-Dokument protokolliert, bei primitiven, wie.z.B. Int32, Decimal, etc., der eigentliche Wert.

Außerdem kann angegeben werden, dass es sich um einen Pflichtwert handelt und eine Beschreibung des Konfigurationstyps.

New-ConfigurationType -ArtifactIdentifier Schleupen.CS.PI.Test_1.0 -IsRequired -Description "Hier steht eine Erklärung!" -SessionToken (Request-SystemSessionToken)
Weitere Administrationsmöglichkeiten per Powershell
Lesen von mehreren Konfigurationswerten
Select-ConfigurationValue -SessionToken $sessionToken -ArtifactIdentifier "Schleupen.CS.MT.BIB.Ausleihen.Ausleihekonfiguration_1.0"

oder

Select-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0"

Liefert eine Liste der Konfigurationswerte zu allen Scopes.

Hier können auch Wildcards verwendet werden:

Select-ConfigurationValue -SessionToken $token -Name * -Namespace * -ExternalVersion *
Lesen eines einzelnen Konfigurationswertes
Get-ConfigurationValue -SessionToken $sessionToken -ArtifactIdentifier "Schleupen.CS.MT.BIB.Ausleihen.Ausleihekonfiguration_1.0" -UserScopeValue "User SID" -BrowserScopeValue "Chrome" -LocalScopeValue "pc-1234"

oder

Get-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -UserScopeValue "User SID" -BrowserScopeValue "Chrome" -LocalScopeValue "pc-1234"

Liefert einen (oder keinen) effektiven Konfigurationswert unter Auswertung der Konfigurationsregeln. Die Scope-Werte sind optional und werden im unterbeschriebenen Suchalgorithmus verwendet, um die Konfigurationswert zu ermitteln.

Beim Lesen von Konfigurationswerten werden Werte verworfen, die zur Abfragezeit nicht gültig sind (ValidFrom/ValidTo). Wenn eine andere Zeit genutzt werden soll kann diese mit dem optionalen Parameter -ValidAt definiert werden:

$validAt = Get-Date
Get-ConfigurationValue -SessionToken $sessionToken -ArtifactIdentifier "Schleupen.CS.MT.BIB.Ausleihen.Ausleihekonfiguration_1.0" -UserScopeValue "User SID" -BrowserScopeValue "Chrome" -LocalScopeValue "pc-1234" -ValidAt $validAt

Im Ergebnis wird außerdem das Element angegeben, aus dem der Konfigurationswert gelesen wurde. Dies kann ggf. ein anderes sein als das im SessionToken, wenn globale Werte benutzt werden.

Vereinfachtes Lesen von primitiven Datentypen

Für den vereinfachten Zugriff existieren weitere Commandlets, welche direkt die primitiven Typen zurückgeben. Die Commandlets entsprechen in Bezug auf Parameter und Aufruf dem bereits beschriebenen Commandlet Get-ConfigurationValue.

Get-BooleanConfigurationValue
Get-StringConfigurationValue
Get-Int32ConfigurationValue
Get-Int64ConfigurationValue
Get-DecimalConfigurationValue
Get-TimeStampConfigurationValue
Get-DateTimeOffsetConfigurationValue
Löschen
Remove-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -Scope User -ScopeValue "User SID"

Löscht den durch Namespace, Name, ExternalVersion, Scope und ScopeValue beschriebenen Konfigurationswert.

Default-Werte
Set-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -Scope User -Document "<AusleiheConfigurationValue><MaxAusleiheTage>10</MaxAusleiheTage></AusleiheConfigurationValue>"

Setzt den Konfigurationswert für den aktuellen Benutzer (der, der die Powershell ausführt).

Set-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -Scope Local -Document "<AusleiheConfigurationValue><MaxAusleiheTage>9</MaxAusleiheTage></AusleiheConfigurationValue>"

Setzt den Konfigurationswert für die lokale Maschine (die, auf der die Powershell ausgeführt wird).

Select-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0"
Get-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -BrowserScopeValue "Chrome"

Liest wie oben die Werte unter Berücksichtigung der Werte aus.

Hinterlegung von Auswertungsregelen

Im Folgenden wird gezeigt, wie eine andere Auswertungsregel als die Default-Regel (User -> Local -> Browser -> Global) hinterlegt und wieder gelöscht werden kann.

# Regel anlegen
$sessionToken = Request-SessionToken -Viewname "Standard" -ElementName "9999" -ElementTypeName "Mandant"
 
$client = Get-ServiceClient Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService_3.0
 
$artifactId = New-Object Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.ArtifactIdentifierContract
$artifactId.ExternalVersion = "1.0"
$artifactId.Namespace = "Schleupen.CS.MT.BIB.Ausleihen"
$artifactId.Name = "Ausleihekonfiguration"
 
$priorityRule = New-Object Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.PriorityRuleContract
$priorityRule.Name = $artifactId
$priorityRule.OrderedScopes = New-Object 'System.Collections.ObjectModel.Collection[Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.ScopeContract]'
$priorityRule.OrderedScopes.Add([Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.ScopeContract]::Local)
$priorityRule.OrderedScopes.Add([Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.ScopeContract]::User)
 
$request = New-Object Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.CreateRequest
$request.PriorityRules = New-Object 'System.Collections.ObjectModel.Collection[Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.PriorityRuleContract]'
$request.PriorityRules.Add($priorityRule)
$request.SessionToken = $sessionToken
 
# Regel auswerten vorher
Get-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -UserScopeValue "User SID 1" -BrowserScopeValue "Chrome" -LocalScopeValue "pc-1234"
 
$response = $client.Create($request)
 
# Regel auswerten nach hinterlegter Regel
Get-ConfigurationValue -SessionToken $sessionToken -Namespace "Schleupen.CS.MT.BIB.Ausleihen" -Name "Ausleihekonfiguration" -ExternalVersion "1.0" -UserScopeValue "User SID 1" -BrowserScopeValue "Chrome" -LocalScopeValue "pc-1234"
 
# Regel lesen
$readRequest = New-Object Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.ReadRequest
$readRequest.Names = New-Object 'System.Collections.Generic.List[Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.ArtifactIdentifierContract]'
$readRequest.Names.Add($artifactId)
$readRequest.SessionToken = $sessionToken
$readRespone = $client.Read($readRequest)
 
# Regel löschen
$deleteRequest = New-Object Schleupen.CS.PI.AIF.Configuration.PriorityRules.EntityService.V3_0.DeleteRequest
$deleteRequest.Name = $artifactId
$deleteRequest.SessionToken = $sessionToken
 
$client.Delete($deleteRequest)
Suche nach globalen Werten in der Systemstruktur

Globale Werte haben eine besondere Bedeutung. Wird auf einem Element kein Wert gefunden, so wird in der Systemstruktur nach globalen Werten auf übergeordneten Elementen gesucht.

x = Element des aktuellen SessionTokens

Beispiel 1

System ------ user: <h/>, local: </i>, browser: </j>, global: </k>
    |
    |
Katalog ------  user: <d/>, local: </e>, browser: </f>, global: </g>
    |
    |
Mandant ------ user: <a/>, local: </b>, browser: </c>, global: </d> x
# liefert </a>
Get-ConfigurationValue -SessionToken $mandantSessionToken -ArtifactIdentifier "Schleupen.CS.PI.AIF.Configuration.Test_1.0"
  • Auf Mandant-Ebene wird ein benutzerspezifischer Wert gefunden ✅

Beispiel 2

System ------ user: <h/>, local: </i>, browser: </j>, global: </k>
    |
    |
Katalog ------  user: <d/>, local: </e>, browser: </f>, global: </g>
    |
    |
Mandant ------ x
# liefert </g>
Get-ConfigurationValue -SessionToken $mandantSessionToken -ArtifactIdentifier "Schleupen.CS.PI.AIF.Configuration.Test_1.0"
  • Auf Mandant-Ebene wird ein benutzerspezifischer Wert gefunden ❌
  • Auf Katalogebene nach globalen Werten gesucht und einer gefunden ✅

Beispiel 3

System ------ user: <h/>, local: </i>, browser: </j>, global: </k>
    |
    |
Katalog ------  
    |
    |
Mandant ------ x
# liefert </k>
Get-ConfigurationValue -SessionToken $mandantSessionToken -ArtifactIdentifier "Schleupen.CS.PI.AIF.Configuration.Test_1.0"
  • Auf Mandant-Ebene wird ein benutzerspezifischer Wert gefunden ❌
  • Auf Katalogebene nach globalen Werten gesucht und keiner gefunden ❌
  • Auf Systemebene nach globalen Werten gesucht und einer gefunden ✅

Beispiel 4

System ------ user: <h/>, local: </i>, browser: </j>, global: </k>
    |
    |
Katalog ------  x
    |
    |
Mandant ------ 
# liefert </k>
Get-ConfigurationValue -SessionToken $katalogSessionToken -ArtifactIdentifier "Schleupen.CS.PI.AIF.Configuration.Test_1.0"
  • Auf Katalog-Ebene wird kein Wert gefunden ❌
  • Auf Systemebene nach globalen Werten gesucht und einer gefunden.✅
Suchalgorithmus zum Finden eines Konfigurationwertes
Verwendungszweckspezifische Konfigurationen

Damit die Funktionalität verwendet werden kann, muss im Castle-Installer ReadFromSystemUsageSpecificConfiguration auf true gesetzt werden.

windsorContainer.Install(new ConfigurationClientInstaller() { ReadFromSystemUsageSpecificConfiguration = true });
Konfigurationswerte

Es wird immer der im aktuellen/übergebenen SessionToken angegebene Verwendungszweck genutzt.
Diese Tatsache macht verwendungszweckspezifische Konfigurationswert spezifisch.

Sollen Konfigurationswerte am Verwendungszweck hinterlegt werden, so gibt es folgende API:

IConfigurationV2.WriteToSystemUsage...);
IConfigurationV2.DeleteFromSystemUsage(...)

Per PowerShell können die folgenden Cmdlets verwendet werden:

Get-SystemUsageConfigurationValue
Set-SystemUsageConfigurationValue
Remove-SystemUsageConfigurationValue
# + weitere für die primitiven Datentypen (z.B. Int32, Boolean, etc.)

Die verwendungszweckspezifischen Konfigurationen werden immer zuerst befragt. Wird kein Konfigurationswert gefunden, wird der normale Algorithmus verwendet.

Konfigurationstypen

Die Konfigurationstypen können ebenfalls für einen Verwendungszweck angelegt werden. Hierzu ist der Parameter ForSystemUsage zu verwenden:

New-ConfigurationType -SessionToken $sessionToken -ArtifactIdentifier "Schleupen.CS.PI.Test123_1.0" -WriteChangeLog -IsRequired -ForSystemUsage
Typisches Vorgehen beim Einrichten eines Systems/neuen Verwendungszwecks
  1. Neuen (Test-)Verwendungszweck erzeugen > es gibt für diesen Verwendungszweck (noch) keine verwendungszweckspezifische Konfigurationswerte
  2. Das Cmdlet Test-SystemUsageConfigurationValue prüft immer über alle Verwendungszwecke, ob alle Required-Konfigurationswerte gesetzt sind
  3. Die fehlenden Konfigurationswerte müssen erstellt werden, solange bis Test-SystemUsageConfigurationValue keine Fehler mehr liefert

Wenn verwendungszweckspezifische Konfigurationswerte automatisch erstellt werden sollen, so kann dies mittels Konfigurationsskripten erreicht werden. Konfigurationsskripte werden nach dem Erstellen von (neuen) Konfigurationsskripte automatisch ausgeführt.

Um verwendungszweckspezifische Konfigurationswerte setzen zu können, muss immer zunächst ein Verwendungszweck vorhanden sein, da dieser über seine GUID identifiziert wird. Eine auf Namen basierende Konvention (Verwendungszweck Test ) wird nicht unterstützt. Grund: Es kann mehrere Test-Verwendungszwecke geben.

Anbindung DI-Container
protected override void OnContainerConfigured(IWindsorContainer windsorContainer)
{
    // ...
    windsorContainer.Install(new ConfigurationClientInstaller(IsInsideWcfOperation));

    base.OnContainerConfigured(windsorContainer);
}

Soll das Muster Transactional Outbox genutzt werden, so kann dies über das Property EnableCommandMessages gesteuert werden. In diesem Fall ist außerdem eine entsprechende Tabelle anzulegen. Darüber hinaus muss eine Referenz auf das Paket Schleupen.CS.PI.AIF.Configuration.Client.TransactionalOutbox ergänzt und der entsprechende Installer angeschlossen werden:

new ConfigurationClientInstaller { IsTransactionalOutboxEnabled = true; }
new ConfigurationClientTransactionalOutboxInstaller()

Stärken und Schwächen

Die in diesem Abschnitt beschriebenen Stärken und Schwächen sollen eine Entscheidungshilfe an die Hand geben, wann dieses Muster eingesetzt werden kann.

Stärken
  • Versionierbar: Es können unterschiedliche Versionen eines Konfigurationswertes erstellt und verwaltet werden
  • Zentralisierung: Alle Informationen zur Beschreibung einer Version werden im Domänenobjekt hinterlegt.
  • Vereinfachte Verwendung von primitiven Datentypen möglich

Alternative Muster

Vereinfachte Verwendung von primitiven Datentypen

Es besteht eine vereinfachte Möglichkeit für den Umgang mit primitiven Datentypen.

Diese Möglichkeit sollte nur verwendet werden, wenn ein einzelner Werte verwaltet wird.
Sobald mehrere Werte konfigurierbar sein müssen, wird die Verwendung des regulären Musters empfohlen.

internal sealed class BuecherAusleihenController : IBuecherAusleihenController
{
    private readonly ConfigurationArtifactIdentifier maxAnzahlGleichzeitigerAusleihenArtifactIdentifier =
        new ConfigurationArtifactIdentifier("Schleupen.CS.MT.BIB.Ausleihen", "MaxAnzahlGleichzeitigerAusleihen", "1.0");

    // ...

    public BuecherAusleihenController(..., IConfigurationV2 configuration, ...)
    {
        if (configuration == null) { throw ExceptionBuilder.ArgumentNull(() => configuration); }
        this.configuration = configuration;
        // ...
    }

    public Ausleihe LeiheBuecherAus(string benutzerSid, Buch[] buecher)
    {
        // Lesen eines int Wertes
        int maxAnzahlGleichzeitigerAusleihen =
                      configuration.ReadInt32(maxAnzahlGleichzeitigerAusleihenArtifactIdentifier, Benutzerkonto.MaxAnzahlGleichzeitigerAusleihenDefault);

        Benutzerkonto benutzerkonto = benutzerkontoRepository.QueryBySidForUpdate(benutzerSid);
        benutzerkonto.SetMaxAnzahlGleichzeitigerAusleihen(maxAnzahlGleichzeitigerAusleihen);
        // ...
    }

    public void SetMaxAnzahlGleichzeitigerAusleihen(int maxAnzahlGleichzeitigerAusleihen)
    {
        // Schreiben von int Werten
        configuration.Write(Scope.Global, maxAnzahlGleichzeitigerAusleihenArtifactIdentifier, maxAnzahlGleichzeitigerAusleihen);
    }
}

Falls ein primitiver Datentyp an einer Stelle verwendet werden soll, an der bisher nur der Zugriff über den ManageCdtConfigurationActivityService möglich ist (bspw. in der UI), kann ein passender CustomDataType erstellt werden. Dieser erhält den Namen des primitiven Datentyps und eine Eigenschaft Value, welche vom gewünschten Datentyp ist. Dadurch kann in der Powershell und im sonstigen Code bereits über die vereinfachten Mittel zugegriffen werden, während in den Prozessartefakten der Zugriff noch über ein entsprechendes Gateway erfolgt.

Cookie Consent mit Real Cookie Banner