Durchsuchbare Dokumentation aufrufen | Zurück zur Dokumentationsübersicht
Navigation: Dokumentationen agorum core > agorum core workflow 3.0
Diese Dokumentation beschreibt Methoden zum Abbrechen, Beenden oder Löschen eines Workflows.
Einen einzelnen Workflow abbrechen
Diese Methode ist die einzige valide Form, um einen einzelnen Workflow ordnungsgemäß abzubrechen. Der Vorteil des gezielten Beendens eines Workflows im Vergleich zum Abbrechen mehrerer Workflows ist, dass der Workflow noch die Möglichkeit hat, den aktuellen Prozess zu verändern. So können Sie etwa noch nach dem Abbrechen einen Status auf die Anhänge setzen.
Mehrere Workflows abbrechen
Diese Methode verwenden Sie primär, wenn Sie schnell alle Workflowdaten zu einem Workflowprozess beseitigen und aufräumen wollen. Dabei beendet das System alle Tokens, die Logdateien stehen jedoch nach wie vor zur Verfügung.
Sie beenden einen Workflow idealerweise, indem Sie ihn über das Outlet des letzten Knotens laufen lassen.
Durch diese Methode löscht das System nur selektierte Objekte. Alle weiteren Objekte, die ein Workflow für seinen Prozess verwendet, beachtet das System nicht. Es entstehen „Leichen“ oder „schlafende Prozesse“, die unbemerkt weiterlaufen, für den Systembetrieb jedoch unbedenklich sind.
Hinweis: Sollten Sie einen Spezialfall vorliegen haben, benötigen Sie eventuell eine andere Methode als die hier vorgestellten und empfohlenen.
Diese Methode dient dazu, eine große Anzahl an Workflowdaten zu einem Workflowprozess schnell zu beseitigen und aufzuräumen. Dabei beendet das System alle Tokens, die Logdateien stehen jedoch nach wie vor zur Verfügung.
Sie finden in der Bedienoberfläche und dort in der Prozessübersicht die Schaltfläche Workflow abbrechen. Hiermit können Sie alle gewählten Prozessschritte abbrechen.
Wenn Sie über diesen Weg alle Workflows abbrechen, dauert das Abbrechen eine gewisse Zeit. Brechen Sie alle Workflows in diesem Falle über ein JavaScript ab.
Im Folgenden erfahren Sie, wie Sie über ein JavaScript von außen alle Workflows abbrechen können.
Setzten Sie die Variable simulated auf false und klicken Sie auf Run.
Vor Änderung
let simulated = true; // Simulation an
Nach Änderung
let simulated = false; // Simulation aus
Ergebnis: Das System bricht alle Tokens / Workflows ab und beseitigt jegliche Workflowdaten und Workflowprozesse.
JavaScript zum Abbrechen aller Workflows
Das folgende JavaScript bricht alle laufenden Workflows auf einmal ab und erzeugt eine Oberfläche, die die Hintergrundaktivitäten während des Abbrechens der Workflowschritte darstellt.
Inhalt des Skripts
/* global sc, sca */ // ----------------------------------------------- Imports ----------------------------------------------- let aguila = require('common/aguila'); let objects = require('common/objects'); let transaction = require('common/transaction'); let workflow = require('common/workflow'); let background = require('/agorum/roi/customers/agorum.composite/js/lib/background'); let context = require('/agorum/roi/customers/acworkflow/js/runtime/context')(sca); let perMan = require('/agorum/roi/customers/acworkflow/js/runtime/persistence-manager')(sca); // ----------------------------------------------- Settings ---------------------------------------------- // Enable/Disable simulation. true = simulate, false = run let simulated = false; // Workflow name of workflow instances to be killed. '*' = every workflow! let workflowName = 'full.qualified.workflow.name'; // ------------------------------------------------------------------------------------------------------- // ----------------------------------------------- Functions ----------------------------------------------- let runInBackground = (callback) => aguila.enter(() => aguila.fork(() => background(p => callback(p)))); // ----------------------------------------------- Main ----------------------------------------------- runInBackground(process => { process.name = (simulated ? '[simulating] ' : '[running] ') + workflowName; process.status = 'Searching workflows'; let query = objects.query('inpath:9999 sys_acw_componenttype:process sys_acw_processstatus:"acworkflow.process.status.active" sys_acw_processname:' + workflowName); let wfCount = query.limit(0).search().total; let currentWf = 0; let instancesDone = {}; // iterate over matching workflows query.limit(1000).iterate('uuid', instance => { let instanceObj = objects.tryFind(instance.uuid); // currentWf += 100; currentWf++; process.status = 'Killing workflow: ' + instance.uuid + ' (' + currentWf + ' / ' + wfCount + ')'; process.progress = (currentWf / wfCount) * 100; if (instanceObj) { // check if workflow instance has already been handeled if (instancesDone[instance.uuid]) return; // this may happen? instancesDone[instance.uuid] = true; let workflowContext = context.loadContext(instanceObj.firstParent.UUID, sca); let allTokens = workflowContext.instance.tokens || []; if (simulated) { allTokens.forEach(t => console.log('killing: ', t.id)); } else { transaction(() => { allTokens.forEach(t => t.kill()); // persist all information to the workflow instance perMan.persist(workflowContext); }); } } }); });
Egal, ob Sie sich innerhalb oder außerhalb eines Workflows befinden, das Ziel ist es, den zu beendenden Workflow zu triggern und die Parameter, die der Workflow selbst interpretieren kann oder muss, zu setzen. Der Workflow bestimmt also letztlich selbst, was er mit den entsprechenden Informationen anfängt.
Es existieren zwei Möglichkeiten, einen laufenden Workflow ordnungsgemäß zu beenden. Sie verwenden bei beiden Möglichkeiten ein externes JavaScript, Sie greifen also von außen in einen Workflow ein, um ihn zu beenden.
Das System beendet den beispielhaften Workflow abort, indem es den Workflow zwingt, den Ausgang über ein Outlet zu gehen.
Der Workflow besteht aus folgenden Knoten:
Das Beispiel besteht aus folgenden Bestandteilen:
Vorteil
Der Workflow beendet sich immer ordnungsgemäß.
Nachteil
Der Workflow beendet sich auch dann, wenn er sich gerade an einer Stelle befindet, an der ein Beenden nicht erwünscht ist.
Im folgenden Beispiel des Workflows abort beendet sich der Workflow, indem das System das Verlassen über ein Outlet erzwingt. Dabei wird ein JavaScript verwendet, das auf die gesetzten Metadaten reagiert.
Hinweise:
Bei allen nachfolgend aufgeführten Bezeichnungen / Variablen / Werten handelt es sich um Beispiele. Sie müssen diese Beispiele nicht 1:1 übernehmen, sondern können eigene Bezeichnungen / Variablen / Werte verwenden.
Das System speichert Metadaten bei jedem commit, erst danach sind sie für eine Aktion und Selektoren oder Ähnliches sichtbar. Das Speichern eines commits löst das System etwa durch eine UI oder einen Delay aus.
Parameter
Im Knoten sind keine Parameter befüllt.
Funktionsweise
Dieser Knoten sorgt dafür, dass der Workflow originale Objekte nicht verändert.
Parameter
Im Knoten sind folgende Parameter befüllt:
Funktionsweise
Dieser Knoten legt fest, dass das System das Metadatum ac_samples_wf_is_deletable mit true belegt, wenn der Workflowprozess an diesem Schritt angekommen ist. Dies ist wichtig, da die dazugehörige Aktion Workflow abbrechen aus dem agorum core smart assistant konfigurator dieses Metadatum verwendet.
Hinweis: Bei dem Metadatum ac_samples_wf_is_deletable handelt es sich bei ac_samples um das Präfix des Konfigurationsprojekts. Kopieren Sie deshalb das Metadatum nicht komplett in Ihren Workflow, sondern verwenden Sie das Präfix Ihres eigenen Konfigurationsprojekts.
Parameter
Im Knoten ist folgender Parameter befüllt:
Die durch das Oberflächenskript erzeugte Oberfläche sieht wie folgt aus:
Im Folgenden sehen Sie das verwendete Skript zum Erzeugen der Oberfläche:
let aguila = require('common/aguila'); // Create form for workflow step. // This sample contains some common elements, feel free to use or remove them let form = aguila.create({ type: 'agorum.composite.form.basic', labelPosition: 'top', elements: [ // some description { type: 'agorum.textDisplay', // use _agorum.workflow.translation.auto.agorum_workflow_samples_test_abort.ui.aguila.key // you have to activate translation in workflow settings text: 'Führen Sie den Workflow fort über den Ok-Button oder brechen Sie den Workflow über das Kontext-Menü ab.' }, // buttons { type: 'agorum.spacer', height: 24 }, { type: 'agorum.hbox', items: [ { type: 'agorum.spacer', flexible: true }, // buttons on right side { type: 'agorum.composite.form.element.button', name: 'ok', text: '_acmsg:ok=Ok', icon: 'aguila-icon check' } ] } ] }); // Listen for actions on the widget form.on('action', action => { // find out, which button has been pressed // and leave the ui node through the associated outlet switch (action.name) { case 'ok': // the form has to be valid, before the ui can be left through the "ok"-outlet if (form.validate()) { form.fire('leave', 'ok'); } break; case 'cancel': // when cancel is pressed, leavel to "cancel"-outlet without validation form.fire('leave', 'cancel'); break; } }); form;
Funktionsweise
Über diesen Knoten erzeugt das System eine aguila-Oberfläche, die eine Beschreibung und eine Schaltfläche enthält, der den Workflow weiterführen lassen soll. Zudem gibt das Skript an, was beim Bestätigen passieren soll (den Workflow fortführen) und was beim Abbrechen (den Workflow abbrechen).
Tipp: Sie können alternativ zur Aktion auch eine Abbrechen-Schaltfläche einbauen.
Parameter
Im Knoten sind folgende Parameter befüllt:
Funktionsweise
Dieser Knoten legt fest, dass das System das Metadatum ac_samples_wf_is_deletable mit false belegt, wenn der Workflowprozess an diesem Schritt angekommen ist. Dies ist wichtig, da die dazugehörige Aktion Workflow abbrechen dieses Metadatum verwendet.
Hinweis: Bei dem Metadatum ac_samples_wf_is_deletable handelt es sich bei ac_samples um das Präfix des Konfigurationsprojekts. Kopieren Sie deshalb das Metadatum nicht komplett in Ihren Workflow, sondern verwenden Sie das Präfix Ihres eigenen Konfigurationsprojekts.
Parameter
Im Knoten ist folgender Parameter befüllt:
Die durch das Oberflächenskript erzeugte Oberfläche sieht wie folgt aus:
Im Folgenden sehen Sie das verwendete Skript zum Erzeugen der Oberfläche:
let aguila = require('common/aguila'); // Create form for workflow step. // This sample contains some common elements, feel free to use or remove them let form = aguila.create({ type: 'agorum.composite.form.basic', labelPosition: 'top', elements: [ // some description { type: 'agorum.textDisplay', // use _agorum.workflow.translation.auto.agorum_workflow_samples_test_abort.ui2.aguila.key // you have to activate translation in workflow settings text: 'Schließen Sie den Workflow über den Ok-Button ab oder gehen Sie zurück zum vorherigen Schritt über den Zurück-Button.' }, // buttons { type: 'agorum.spacer', height: 24 }, { type: 'agorum.hbox', items: [ // buttons on left side { type: 'agorum.composite.form.element.button', name: 'back', text: '_acmsg:cancel=Zurück', icon: 'aguila-icon cancel' }, { type: 'agorum.spacer', flexible: true }, // buttons on right side { type: 'agorum.composite.form.element.button', name: 'ok', text: '_acmsg:ok=Ok', icon: 'aguila-icon check' } ] } ] }); // Listen for actions on the widget form.on('action', action => { // find out, which button has been pressed // and leave the ui node through the associated outlet switch (action.name) { case 'ok': // the form has to be valid, before the ui can be left through the "ok"-outlet if (form.validate()) { form.fire('leave', 'ok'); } break; case 'back': // when cancel is pressed, leavel to "cancel"-outlet without validation form.fire('leave', 'back'); break; } }); form;
Funktionsweise
Über diesen Knoten erzeugt das System eine aguila-Oberfläche, die eine Beschreibung und zwei Schaltflächen enthält.
Parameter
Im Knoten sind keine Parameter befüllt.
Funktionsweise
Dieser Knoten signalisiert, dass der Workflow beendet wurde. Er erfüllt keine weiteren Funktionen.
Parameter
Im Knoten sind keine Parameter befüllt.
Funktionsweise
Dieser Knoten signalisiert, dass der Workflow von außen (durch das JavaScript der Aktion „Workflow abbrechen“) abgebrochen wurde. Er erfüllt keine weiteren Funktionen.
Parameter
Im Knoten sind folgende Parameter befüllt:
Funktionsweise
Dieser Knoten legt fest, dass das System das Metadatum ac_samples_wf_status mit dem Wert Abgebrochen belegt, wenn der Workflowprozess an diesem Schritt angekommen ist.
Hinweis: Bei dem Metadatum ac_samples_wf_is_deletable handelt es sich bei ac_samples um das Präfix des Konfigurationsprojekts. Kopieren Sie deshalb das Metadatum nicht komplett in Ihren Workflow, sondern verwenden Sie das Präfix Ihres eigenen Konfigurationsprojekts.
Parameter
Im Knoten ist folgender Parameter befüllt:
Funktionsweise
In diesem Knoten filtert, sammelt und stellt das System die Metadaten zu ac_samples bereit.
Hinweis: Wenn Sie einen Workflow beendet haben, ist in den Logs zusätzlich zu sehen, dass das System den Workflowschritt über ein entsprechendes Outlet verlassen hat.
Um den Workflow über ein JavaScript von außen kontrolliert abzubrechen, existiert die Aktion Workflow abbrechen aus dem agorum core smart assistant konfigurator.
In der folgenden Abbildung sehen Sie, wie die Aktion Workflow abbrechen angelegt ist.
Hinweise:
Für das Anlegen einer Aktion im agorum core smart assistant konfigurator siehe Elemente im agorum core smart assistant anlegen.
Der Selektor [nameExtension=/acwt/i][~ac_samples_wf_is_deletable=true] definiert ausschließlich, ob eine Aktion sichtbar ist oder nicht. Wird ein JavaScript ohne Aktion aufgerufen, müssen Sie selbstständig prüfen, ob das dazugehörige Metadatum an der gewünschten Stelle sitzt. Beim Durchlaufen des Workflows mit entsprechendem Metadatum ist unklar, ob der Workflow durch das entsprechende Outlet verlassen wird.
/* global sc, sca, folder, objects, data */ let workflow = require('common/workflow'); let LEAVE = 'abort'; objects.forEach(obj => leaveWorkflowStep(obj.ID)); function leaveWorkflowStep(tokenId) { // Als Erstes annehmen workflow.set(tokenId, { '_sys_acw_action': { type: 'acquire', force: true } }, sc); // "leave" ausführen workflow.set(tokenId, { '_sys_acw_action': { type: 'leave', outlet: LEAVE } }, sc); }
Über diese Möglichkeit erzwingt das System nicht den Ausgang über ein Outlet, sondern ruft ein wartendes Skript auf (über den Knoten script1), dem Parameter übergeben werden können.
Der Workflow besteht aus folgenden Knoten:
Das Beispiel besteht aus den folgenden Bestandteilen:
Vorteil
Der Workflow kann nicht dazu gezwungen werden, dass er durch das Verlassen eines Outlets beendet wird. Wenn der Workflow an einer Stelle angelangt ist, an dem es nicht gewünscht ist, dass er beendet wird, geschieht dies nicht.
Nachteil
Greift etwas von außen auf den Workflow zu, wie hier in diesem Beispiel, registriert nur das Update Script diesen Zugriff und kennt deshalb nicht unbedingt den Zustand des anderen Tokens, das durch den Knoten fork entstanden ist. Das Skript kann entweder eine eigene Logik erstellen, um mit dem Haupttoken zu kommunizieren, oder es bricht den Workflow „hart“ ab. Die ist etwa sinnvoll, wenn Daten oder Anhänge anderweitig gesichert wurden oder Ähnliches und das weitere Ergebnis des Haupttokens nicht mehr relevant ist oder um Testworkflows aufzuräumen.
Hinweis: Bei allen nachfolgend aufgeführten Bezeichnungen / Variablen / Werten handelt es sich um Beispiele. Sie müssen diese Beispiele nicht 1:1 übernehmen, sondern können eigene Bezeichnungen / Variablen / Werten verwenden.
Parameter
Im Knoten sind keine Parameter befüllt.
Funktionsweise
Dieser Knoten sorgt dafür, dass das System originale Objekte nicht verändert.
Parameter
Im Knoten sind keine Parameter befüllt.
Funktionsweise
Dieser Knoten sorgt dafür, dass mehrere Prozesse parallel ablaufen können, und erzeugt ein weiteres Token.
Parameter
Im Knoten ist folgender Parameter befüllt:
Die durch das Oberflächenskript erzeugte Oberfläche sieht wie folgt aus:
Im Folgenden sehen Sie das verwendete Oberflächenskript:
let aguila = require('common/aguila'); // Create form for workflow step. // This sample contains some common elements, feel free to use or remove them let form = aguila.create({ type: 'agorum.composite.form.basic', labelPosition: 'top', elements: [ // some description { type: 'agorum.textDisplay', // use _acmsg:key=Text for translation // you have to activate translation in workflow settings text: 'Brechen Sie entweder alle Vorgänge ab über den Abort-Button oder führen Sie den Workflow fort über den Ok-Button.' }, // buttons { type: 'agorum.spacer', height: 24 }, { type: 'agorum.hbox', items: [ // buttons on left side { type: 'agorum.composite.form.element.button', name: 'cancel', text: 'Abort', icon: 'aguila-icon cancel' }, { type: 'agorum.spacer', flexible: true }, // buttons on right side { type: 'agorum.composite.form.element.button', name: 'ok', text: 'Ok', icon: 'aguila-icon check' } ] } ] }); // Listen for actions on the widget form.on('action', action => { // find out, which button has been pressed // and leave the ui node through the associated outlet switch (action.name) { case 'ok': // the form has to be valid, before the ui can be left through the "ok"-outlet if (form.validate()) { form.fire('leave', 'ok'); } break; case 'cancel': // when cancel is pressed, leavel to "cancel"-outlet without validation form.fire('leave', 'cancel'); break; } }); form;
Funktionsweise
Über diesen Knoten erzeugt das System eine Oberfläche zum Kontrollieren der aktuellen Anhänge.
Parameter
Im Knoten sind folgende Parameter befüllt:
Funktionsweise
Durch diesen Knoten erhält der Workflow den Status Abgebrochen. Dies wird über ein Kontrollfenster erreicht.
Parameter
Im Knoten sind folgende Parameter befüllt:
Inhalt des Enter scripts
/* global sc, sca, token, instance, outlets, inlet, parameters */ // Wir müssen diesen Token finden! // Die tokens haben bis zu diesem Knoten alle die gleichen Informationen, daher wissen wir nicht, welches wir beinflussen können. // Wir setzen also nur auf dieses eine Token ein neues Metadatum, sodass wir danach suchen können: token.variables.academy_workflow_wf_type = 'abortable'; // Gibt es hier kein "leave", dann verbleibt der Knoten im Wartezustand // Im Wartezustand kann der Knoten nur von außen durch den Aufruf des Tokens aufgelöst werden // Siehe common/workflow // workflow.set(.......);
Inhalt des Update scripts
/* global sc, sca, token, instance, outlets, inlet, parameters */ /* Workflow gehört zum Skript '/agorum/roi/customers/agorum.workflow.samples/js/agorum-workflow-samples-abortOverUpdate.js' */ // Wir haben von außen neue Variablen bekommen: // _message und _docid // Daran können wir prüfen, ob wir auch wirklich gemeint sind und was die Nachricht uns sagt let message = token.variables._message || {}; let hasSameDocId = token.variables._docid === token.variables.academy_workflow_docid; console.log('Nachricht bekommen', token.variables._docid, message); // Zurücksetzen der Nachricht, damit nicht aus Versehen das Gleiche ausgeführt wird, wenn der n. Sender vergisst, die Werte zu überschreiben. token.variables._docid = null; token.variables._message = null; if (message.abort) { token.leave(""); } else if (message.addAttachment) { // Zum Beispiel könnte hier ein Anhang angehängt oder es könnten weitere Steuerungen übernommen werden // ... // token.variables.sys_acw_attachments.push(token.variables._addAttachment); } else { // Mache nichts console.log('Nachricht bekommen, die nicht verstanden wird'); }
Funktionsweise
Dieser Knoten sorgt dafür, dass der Workflow auf weitere Anhänge wartet.
Parameter
Im Knoten sind folgende Parameter befüllt:
Funktionsweise
Durch diesen Knoten erhält der Workflow den Status Dokumentenbündel komplett!
Parameter
Im Knoten ist folgender Parameter befüllt:
Funktionsweise
Dieser Knoten bestimmt, dass nur eine gewisse Anzahl an Tokens abgeschlossen sein muss, um den gesamten Workflow zu beenden, in diesem Fall ein Token.
Parameter
Im Knoten ist folgender Parameter befüllt:
Funktionsweise
Dieser Knoten gibt eine Nachricht in der Konsole aus, wenn der Workflow beendet ist.
/* global sc */ /* jslint unused: true */ let objects = require('common/objects')(sc.asAdmin()); let workflow = require('common/workflow'); /* Gehört zum Workflow 'agorum.workflow.samples.abortOverUpdate' und bricht diesen ab. Der Workflow bekommt eine Nachricht, mit der er selbst entscheiden kann, was er mit dem Abbruch macht. Daher ist ein Update Skript nötig, das darauf hört. */ // DocId als Beispiel zum Einschränken des Workflows auf einen bestimmten Workflow oder bestimmtes Dokument let docId = 'AAB12'; // Nach dem Workflow suchen let query = 'inpath:9999 academy_workflow_wf_type:"abortable" academy_workflow_docid_ci:"' + docId + '"'; let wfToken = objects.query(query).limit(2).find(); // Token des Workflows gefunden, jetzt können wir unserer Nachricht übergeben if (wfToken && wfToken[0]) { let tokenId = wfToken[0].UUID; let wfData = { // _addAttachment: token.variables.sys_acw_attachments[0], _message: { abort: true }, _docid: docId }; // Daten an den Workflow übergeben workflow.set(tokenId, wfData, sc); 'Nachricht an Workflow übermittelt'; } else { 'Kein Workflow gefunden'; }
/* global sc */ /* jslint unused: true */ let objects = require('common/objects')(sc.asAdmin()); let workflow = require('common/workflow'); /* Gehört zum Workflow 'agorum.workflow.samples.abortOverUpdate' und bricht diesen ab. Der Workflow wird gezwungen, einen bestimmten Weg zu nehmen. */ // DocId als Beispiel zum Einschränken des Workflows auf einen bestimmten Workflow oder bestimmtes Dokument let docId = 'AAB12'; // Nach dem Workflow suchen let query = 'inpath:9999 academy_workflow_wf_type:"abortable" academy_workflow_docid_ci:"' + docId + '"'; let wfToken = objects.query(query).limit(2).find(); // Token des Workflows gefunden, jetzt können wir unserer Nachricht übergeben if (wfToken && wfToken[0]) { let tokenId = wfToken[0].UUID; // "leave" definieren und Variable "resubmitInfo" verändern // Der Workflow muss zugewiesen sein, um leave benutzen zu können. // wenn nicht, kann zuvor ein acquire aufgerufen werden let data = { '_sys_acw_action': { type: 'acquire', force: true } }; // Als Erstes annehmen workflow.set(tokenId, data, sc); data = { '_sys_acw_action': { type: 'leave', variables: { abortText: 'Worfklow beendet' }, outlet: '' // default-Outlet } }; // Dann "leave" ausführen workflow.set(tokenId, data, sc); 'Abbruch im Workflow wurde erzwungen.'; } else { 'Kein Workflow gefunden.'; }
Löschen Sie einen aktiven Workflow nicht, sondern beenden Sie den Workflow immer ordnungsgemäß. Wenn Sie einen Workflow löschen, während er aktiv ist, verbleiben „schlafende“ Prozesse im System. Diese verbleibenden Prozesse sind für den Systembetrieb jedoch unbedenklich.
Sollten Sie einen Workflow auf diese Weise gelöscht haben, stellen Sie ihn über den Serverpapierkorb wieder her und beenden Sie den Workflow ordnungsgemäß.
Sollten Sie einen Workflow auf diese Weise gelöscht haben, stellen Sie ihn über den Serverpapierkorb wieder her und beenden Sie den Workflow ordnungsgemäß.
Achtung: Datenverlust durch Verwenden der Schaltfläche Löschen (ohne Papierkorb). Der Workflow ist in diesem Falle nicht mehr wiederherstellbar. Verwenden Sie diese Schaltfläche nur, wenn Sie den Workflow nicht mehr benötigen.