Allgemeine Informationen zum Thema "Scripting" finden Sie hier.
2. Intrexx-Standardbibliothek
Im Groovy-Skripteditor
haben Sie im Bereich Bibliotheken
Zugriff auf die Intrexx-Standardbibliothek. Wenn Sie einen Eintrag in der Bibliothek markiert haben, finden Sie
unten rechts die folgenden Schaltflächen:
Beschreibung anzeigen
Hier finden Sie eine Beschreibung der aktuell ausgewählten Funktion mit Beispiel-Skript.
Link öffnen
Verlinkt auf entsprechende Seiten mit weiterführenden Informationen.
Dabei wird jeweils genau die Seite mit den Klassen, Interfaces, Methoden oder Properties geöffnet,
die Sie für die aktuell markierte Funktion verwenden können.
2.1. Applikationsstruktur
2.1.1. Applikations-Property aus Datensatz-Objekt
Liest Applikationseigenschaften aus dem Datensatz-Objekt.
Ersetzen Sie im Beispiel-Skript "meineMethode()" mit der gewünschten Methode.
Alle im Intrexx-Standard verwendeten Textelemente sind in den globalen Sprachkonstanten definiert.
Allgemeine Informationen zu diesem Thema finden Sie
hier.
2.2.1. Zugriff auf globale Sprachkonstante
Liefert den Wert, den die globale Sprachkonstante in der
Portal-Standardsprache hat.
Ersetzen Sie im Beispiel-Skript "PORTAL_CONST_NAME" mit dem Namen der gewünschten Sprachkonstante.
Beispiel
def strValue = g_i18n.BUTTON_NEXT
Liefert "Weiter" (Beschriftung der "Weiter"-Schaltfläche,
die Sie in vielen Dialogen finden, in deutsch, der Standardsprache des Beispielportals.
2.2.2. Zugriff auf globale Sprachkonstante in einer bestimmten Sprache
Liefert den Wert, den die globale Sprachkonstante in einer bestimmten Portalsprache hat.
Ersetzen Sie im Beispiel-Skript "PORTAL_CONST_NAME" mit dem Namen der gewünschten Sprachkonstante.
Beispiel
def lang = g_i18n.language("en")
Liefert den Wert, den die globale Sprachkonstante in der englischen Spracheinstellung hat.
Snippet
def lang = g_i18n.language("Sprachcode")
def strValue = lang.PORTAL_CONST_NAME
2.2.4. Zugriff auf Sprachkonstante einer Applikation in einer bestimmten Sprache
Liefert den Wert, den die Applikations-Sprachkonstante in einer
bestimmten Portalsprache hat. Ersetzen Sie im Beispiel-Skript "APP_CONST_NAME" mit dem Namen der gewünschten Sprachkonstante.
Als Sprachcode setzen Sie z.B. "en" für englisch ein.
Klasse, mit der geprüft werden kann, ob die durch Zugriffsanfragen
basierend auf der aktuell gültigen Sicherheitsrichtlinie zugelassen oder abgelehnt werden sollen.
Objekt zur Generierung und Ausführung von Datenbankabfragen.
An Stelle von "executeAndGetScalarValue" wird die Verwendung
der typisierten Methoden (z.B. executeAndGetScalarValueIntValue, executeAndGetScalarStringValue)
empfohlen.
Snippet
//Aufbauen eines Prepared Statements
def stmt = g_dbQuery.prepare(conn, "SELECT * FROM MYTABLE WHERE LID = ?")
stmt.setInt(1, iLid)
stmt.executeQuery()
stmt.close()
//Abfrage eines einzelnen Wertes
def iMax = g_dbQuery.executeAndGetScalarValue(conn, "SELECT MAX(LID) FROM MYTABLE", 0)
Zugriff auf das temporäre Arbeitsverzeichnis des Prozesses auf dem Server.
Das Verzeichnis ist für alle nachfolgenden Prozess-Elemente verfügbar, bis der Prozess beendet ist.
Nur in Prozessen
verfügbar - beinhaltet das Ereignis, das den aktuellen Prozess auslöste.
Zu beachten ist, dass Vergleiche auf das aktuelle Event (s. Skript-Beispiel) immer auf die Interfaces
und nie auf die konkreten Klassen auszuführen sind.
Snippet
import de.uplanet.lucy.server.workflow.event.*
if (g_event instanceof IGlobalTimerWorkflowEvent)
//Hier Skript, mit dem auf ein Timerevent reagiert wird, einfügen.
Enthält die Exception, die aufgefangen wurde. Diese muss untersucht und dann entschieden werden, ob sich
der ErrorHandler sich dafür zuständig erklärt. Häufige Kriterien hierfür sind:
- Die Exception wurde von einer Exception eines bestimmten Typs ausgelöst.
- Die Exception wurde von einer Exception eines bestimmten Typs ausgelöst
und die Fehlermeldung hat einen bestimmten Inhalt (beginnt z.B. mit "my-custom-prefix:").
Vgl. auch readme.txt und handler_50_xxx.groovy.example im
Portalverzeichnis internal/system/vm/html/errorhandler/custom.
Intrexx bietet eine Vielzahl an erweiterten Möglichkeiten der prozessgesteuerten Benutzerverwaltung.
Mit Zugriffsobjekten und –methoden in Groovy-Aktionen können u.a. neue Benutzer angelegt und verwaltet werden.
Als Einstiegspunkt für die Organisationsstruktur eines Portals in Prozessen
dient das global verfügbare und bereits initialisierte Objekt g_om. Damit können grundlegende UseCases wie
z.B. das Suchen eines Benutzers oder das Generieren eines neuen Passworts umgesetzt werden.
Diese Methoden sind wie "normale" Methodenaufrufe zu verwenden. Hier finden Sie alle zur Verfügung stehenden Methoden
in unseren JavaDocs:
// Ändern des Passwworts des übergebenen Benutzers.
g_om.changePassword(g_session.user, "SECRET")
// Generieren und Versenden eines neuen Passworts an den übergebenen Benutzer.
g_om.generateAndSendPassword(g_session.user)
// Suchen eines Benutzers anhand einer GUID.
def user = g_om.getUser("C10579449052F85D9C3FF3C2824348FCE020A22E")
// Klassifizieren einer Liste von GUIDs. Übergeben werden kann eine Liste mit GUIDs
// oder ein Text (z.B. Inhalt eines Datenfelds einer Mehrfachauswahl).
def guids = ["AE39A904172F5867DA23DE289D1D6B7967420DC0", "6AA80844C3C99EF93BF4536EB18605BF86FDD3C5", g_session.user.guid]
def classified = g_om.classifyGuids(guids) //guids = Collection oder String
//Ergebnis ist eine Map mit den kategorisierten GUIDs.
//z.B. {containers=[], users=[7312F993D0DA4CECCA9AE5A9D865BE142DE413EA],
// unclassified=[AE39A904172F5867DA23DE289D1D6B7967420DC0],
// sets=[6AA80844C3C99EF93BF4536EB18605BF86FDD3C5]}
println(classified)
//Weitere Filterung auf bestimmte Objektarten
println(classified.users)
println(classified.containers)
println(classified.sets)
println(classified.unclassified)
//Liefert die Anzahl aller nicht-anonymen Session.
g_om.getNonAnonymousActiveSessionCount()
Darüber hinaus verfügt das Objekt g_om noch über einige Methoden, die in Verbindung mit einer
Closure aufgerufen werden, um weiterführende Aktionen zu realisieren. Zu erkennen sind diese Methoden
an dem in den JavaDocs
angegebenen Parameter vom Typ groovy.lang.Closure, z.B. GroovyOrgBuilder.createUser(groovy.lang.Closure p_closure).
Innerhalb einer solchen Closure können Methoden jener Klasse aufgerufen werden, die in den jeweiligen hinterlegten Links dokumentiert sind.
Folgende Methoden sind mit einer Closure aufrufbar:
g_om.createUser(groovy.lang.Closure p_closure)
Damit kann ein neuer Intrexx-Benutzer angelegt werden. Dabei können innerhalb der Closure
die folgend aufgelisteten Properties gesetzt werden, wobei die Properties name und loginName erforderlich,
die restlichen optional sind.
Property
Datatype
birthday
Date
city
String
container
Object
country
String
defaultLanguage
String
defaultLayout
String
deletable
boolean
deleted
boolean
description
String
disabled
boolean
dn
String
emailBiz
String
emailHome
String
employeeNo
String
enterDate
Date
externalLogin1
String
externalLogin2
String
externalLogin3
String
externalPassword1
String
externalPassword2
String
externalPassword3
String
externalPrimaryGroupId
int
female
boolean
firstName
String
fullName
String
gender
int
guid
String
id
int
internalUsn
int
lastName
String
loginDomain
String
loginDomainLwr
String
loginName
String
loginNameLwr
String
male
boolean
memberOf
Collection<?>
middleName
String
name
String
password
String
passwordChangedDate
Date
passwordExpires
boolean
passwordHash
String
phoneBiz
String
phoneFax
String
phoneHome
String
phoneMobileBiz
String
phoneMobileHome
String
phonePager
String
poBox
String
postalCode
String
priority
int
rplGuid
String
salt
String
showUser
boolean
state
String
street
String
timeZone
TimeZone
title
String
userImageContentType
String
userImageFile
File
userImageMetaInfo
String
Bei den Properties "container" und "memberOf" können wahlweise die GUIDs, die eindeutigen
Namen der Container, Rollen, Sets oder Gruppen und Pfade in der Organisationsstruktur angegeben werden.
Gibt alle aktuell eingeloggten Benutzer aus. Über p_bIncludeAnonymous kann angegeben werden,
ob anonyme Sessions in das Ergebnis mitaufgenommen werden sollen. Über die Groovy-Closure
können weitere Filterungen vorgenommen werden.
Gibt alle aktuell eingeloggten, nicht-anonymen Benutzer ohne doppelte Vorkommen aus.
Über die Groovy-Closure können analog zu g_om.getLoggedOnUsers(boolean p_bIncludeAnonymous, groovy.lang.Closure p_closure)
weitere Filterungen vorgenommen werden.
"00A303288634E154D755732E478F2BE0D9AD36F7" ist die aus der Benutzerverwaltung
kopierte GUID der Gruppe. Mehrere Gruppen-GUIDs bzw. Set-GUIDs sind möglich. Weitere Informationen finden Sie hier:
Diese Klasse dient der Prüfung und Abfrage von Berechtigungen.
Die Verwendung wird in der Vorlage "JSON-Antwort"
für den dortigen Anwendungsfall gezeigt. checkPermission(Permission) und check(Closure) prüfen,
ob die gewünschten Berechtigungen gewährt werden. Andernfalls wird eine java.security.AccessControlException geworfen.
hasPermission(Permission) und has(Closure) funktionieren analog, liefern jedoch einen boolean-Wert,
der angibt, ob die angeforderten Berechtigungen gewährt werden oder nicht. Die Closure-Methoden delegieren
an das o.g. GroovyIxAccessControllerDelegate-Objekt und verlangen eine Map, die den Objektnamen Aktionen zuweist.
Beispiel
Prüfe Zugriffsberechtigung an der Applikation <application GUID>,
Leseberechtigungen an der Datengruppe <data group GUID> sowie Schreibberechtigungen
an der Datengruppe <another data group GUID>.
g_permissions.check {
application("<application GUID>": "access")
dataGroup("<data group GUID>": "read", "<another data group GUID>": "write,create")
}
Zugriff auf den Portlet-Pool, der gefiltert werden soll
(Collection von Portlets), zum einen wirklich im Portlet-Pool und zum anderen beim Rendern der Portlets.
Lesender und schreibender Zugriff auf den aktuellen Datensatz. Nur verfügbar innerhalb von
Groovy-PageActionHandlern. Beispiel:
def iLid = g_rwRecord["0D8F13B2B43B128DB23C0C1CC8C5DC1143C9D826"].value // datafield (PK) (S) ID
Zugriff auf den aktuellen Request, z.B. Auslesen von Requestvariablen im Prozess.
Diese Variable ist nur definiert, wenn das Skript von einem Web-Request aufgerufen wurde.
RtCache - Zugriff auf Datengruppen, Applikationen, Felder etc.
Beispiel
//Finde alle Datengruppen der Applikation mit der GUID 68C97BF4D89E8466BDE08AF03A4EF95F5B23AF72
def datagroups = g_rtCache.dataGroups.findAll {it.appGuid == "68C97BF4D89E8466BDE08AF03A4EF95F5B23AF72"}
Shared State, in den Variablen und Werte
geschrieben und wieder ausgelesen werden können.
Beispiel
//Variable in Shared State schreiben
g_sharedState.meineVariable = "Mein Wert"
//Variable aus Shared State lesen
def strValue = g_sharedState.meineVariable
Liefert den vollständigen StackTrace eines aufgetretenen Fehlers als String zurück.
Die Closure "getStackTraceString()" benötigt einen Parameter vom Typ
java.lang.Throwable, also eine Exception.
2.6.1.2. Datengruppe in SQL über GUID referenzieren
Mit Hilfe dieser Clientfunktion kann eine Datengruppe über ihre GUID statt über ihren Namen referenziert werden.
Damit muss in SQL-Statements nicht der Name der Datengruppe fest hinterlegt werden, womit Probleme
beim Import oder bei Änderungen an der Datengruppe vermieden werden. Nur verfügbar über das Intrexx Datenbank-API.
Beispiel
g_dbQuery.executeAndGetScalarValue(conn, "SELECT COUNT(LID) FROM DATAGROUP('DAF7CECF66481FCABE50E529828116EAFE906962')")
An Stelle von "executeAndGetScalarValue" wird die Verwendung
der typisierten Methoden (z.B. executeAndGetScalarValueIntValue, executeAndGetScalarStringValue)
empfohlen.
Snippet
def strName = g_rtCache.dataGroups["<GUID der Datengruppe>"].name
Bitte beachten: Soll das Statement wiederverwendet werden, z.B. innerhalb einer Schleife, ist die Variante als Prepared Statement ohne Closure effizienter.
2.6.2.5. Vorbereitete Anweisung mit UPDATE (mit Closure)
Führt eine vorbereitete Anweisung mit einem UPDATE-Statement mit Closure aus.
Beispiel
def conn = g_dbConnections.systemConnection
g_dbQuery.executeUpdate(conn, "UPDATE DATAGROUP('7AFAF7CB5DE281D35F05D96FCD96CE27692C110F') SET STRTEXT = ? WHERE DATE < ?") {
setString(1, "Example text")
setTimestamp(2, now().withoutFractionalSeconds)
}
Bitte beachten: Soll das Statement wiederverwendet werden, z.B. innerhalb einer Schleife, ist die Variante als Prepared Statement ohne Closure effizienter.
2.6.2.7. Vorbereitete Anweisung mit DELETE (mit Closure)
Führt eine vorbereitete Anweisung mit einem DELETE-Statement mit Closure aus.
Beispiel
def conn = g_dbConnections.systemConnection
g_dbQuery.executeUpdate(conn, "DELETE FROM DATAGROUP('7AFAF7CB5DE281D35F05D96FCD96CE27692C110F') WHERE ID > ?"){
setInt(1, 5)
}
Bitte beachten:
Soll das Statement wiederverwendet werden, z.B. innerhalb einer Schleife, ist die Variante als Prepared Statement ohne Closure effizienter.
Snippet
def conn = g_dbConnections.systemConnection
g_dbQuery.executeUpdate(conn, "DELETE FROM DATAGROUP('<DATAGROUP_GUID>') WHERE <CONDITION>"){
//setInt(1, 1)
//setString(2, "Example text")
//setTimestamp(3, now().withoutFractionalSeconds)
//setBoolean(4, true)
Liest einen einzelnen Wert aus einer Datenbankabfrage aus. Ist die Ergebnismenge leer oder null, wird der mit fallbackValue definierte Wert zurückgegeben.
Soll der Datentyp der Rückgabe genauer spezifiziert werden, können typisierte Methodenaufrufe wie z.B. executeAndGetScalarBooleanValue(...) erfolgen.
Beispiel
def value = g_dbQuery.executeAndGetScalarValue(conn, "SELECT MAX(ID) FROM DATAGROUP('7AFAF7CB5DE281D35F05D96FCD96CE27692C110F')", 0)
oder mit vorbereiteter Anweisung
def value = g_dbQuery.executeAndGetScalarValue(conn, "SELECT MAX(ID) FROM DATAGROUP('7AFAF7CB5DE281D35F05D96FCD96CE27692C110F') WHERE DTEDIT < ?", 0) {
setTimestamp(1, now().withoutFractionalSeconds)
An Stelle von "executeAndGetScalarValue" wird die Verwendung
der typisierten Methoden (z.B. executeAndGetScalarValueIntValue, executeAndGetScalarStringValue)
empfohlen.
Snippet
def conn = g_dbConnections.systemConnection
def value = g_dbQuery.executeAndGetScalarValue(conn, "SELECT <COLUMNS> FROM DATAGROUP('<DATAGROUP_GUID>') WHERE <CONDITION>", <FALLBACK_VALUE>) {
//setString(1, "Example text.")
}
2.6.2.9. Einzelner Wert aus vorbereiteter Datenbankabfrage
Liest einen einzelnen Wert aus einer Datenbankabfrage aus. Ist die Ergebnismenge leer oder null, wird der mit fallbackValue definierte Wert zurückgegeben.
Soll der Datentyp der Rückgabe genauer spezifiziert werden, können typisierte Methodenaufrufe wie z.B. executeAndGetScalarBooleanValue(...) erfolgen.
Beispiel
def stmt = g_dbQuery.prepare(conn, "SELECT MAX(LID) FROM DATAGROUP('7AFAF7CB5DE281D35F05D96FCD96CE27692C110F')")
def value = stmt.executeAndGetScalarValue(0)
stmt = Safely.close(stmt)
An Stelle von "executeAndGetScalarValue" wird die Verwendung
der typisierten Methoden (z.B. executeAndGetScalarValueIntValue, executeAndGetScalarStringValue)
empfohlen.
Ruft den zu Grunde liegenden Webservice auf. Gilt nur für Skripts, die innerhalb eines Webservices definiert sind.
Snippet
g_ws.invoke()
2.7.2. Webservice-Eingabewerte auslesen
Auslesen von Werten, die einem Webservice als Eingabeparameter übergeben werden.
Als Variablenname ist der Name der Kontrolle anzugeben, die den Wert enthält.
Beispiel
g_ctx.requestVars.textcontrolD72A9620
Snippet
g_ctx.requestVars.
2.7.3. Webservice-Rückgabewerte auslesen
Auslesen von Werten, die einem Webservice als Rückgabeparameter übergeben werden.
Als Variablenname ist der Name der Kontrolle anzugeben, in die der Rückgabewert geschrieben wird.
Beispiel
g_ctx.bpeeVars.textvcontrol72EF4A0B.value
Snippet
g_ctx.bpeeVars..value
2.8. Fallunterscheidung
2.8.1. switch-Anweisung für Groovy-Bedingung
Anwendbar in Prozessen. Die Rückgabewerte entsprechen den ausgehenden Verbindungen
(Verbindungs-ID) der Groovy-Bedingung.
Snippet
switch (g_record[""].value)
{
case "expected value 1":
return connectionId1
case "expected value 2":
return connectionId2
default:
return connectionId3
}
2.8.2. switch-Anweisung für Datengruppenereignisse
Anwendbar in Prozessen.
Snippet
import de.uplanet.lucy.server.workflow.event.IAfterCreateDataGroupWorkflowEvent
import de.uplanet.lucy.server.workflow.event.IAfterUpdateDataGroupWorkflowEvent
import de.uplanet.lucy.server.workflow.event.IBeforeDeleteDataGroupWorkflowEvent
import de.uplanet.lucy.server.workflow.event.INotifyDataGroupWorkflowEvent
switch (g_event)
{
case IAfterCreateDataGroupWorkflowEvent:
g_log.info("A new record was inserted.")
break
case IAfterUpdateDataGroupWorkflowEvent:
g_log.info("A record was updated.")
break
case IBeforeDeleteDataGroupWorkflowEvent:
g_log.info("A record will be deleted.")
break
case INotifyDataGroupWorkflowEvent:
g_log.info("A timer resubmitted a record.")
break
default:
g_log.warn("Unhandled event ${g_event}.")
break
}
2.8.3. Datensätze bei globalen Datengruppen-Timern
Unterscheidung zwischen dem erstem und den nachfolgenden Datensätzen bei globalen Datengruppen-Timern.
Snippet
if (g_sharedState["wasHere${g_guidSelf}"])
{
// we were here before
}
else
{
// we are here for the first time
g_sharedState["wasHere${g_guidSelf}"] = true
}
2.9. Mathematische Berechnungen
2.9.1. Kaufmännisches Runden
Kaufmännisches Runden mit optionaler Angabe der Nachkommastellen.
Hier finden Sie Skript für die Formatierung von Datumswerten.
Snippet
import java.text.SimpleDateFormat
// specify the time zone
def tz = g_session.user.timeZone
//def tz = de.uplanet.lucy.server.DefaultTimeZone.get()
//def tz = TimeZone.getTimeZone("Europe/Berlin")
assert tz != null
// the date/time to be formatted
def dt = new Date()
// the date format
// https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html
def fmt = new SimpleDateFormat("yyyy-MM-dd")
fmt.setTimeZone(tz)
println(fmt.format(dt))
Ein Datensatz beinhaltet Daten für ein Start- und ein Enddatum. Berechnet wird die Zeitspanne zwischen diesen beiden Datumswerten.
Bitte beachten Sie, dass hier keine Zeitzonen berücksichtigt werden.
Snippet
def conn = g_dbConnections.systemConnection
def dtStart = g_record["GUID"].value // datafield startDate
def dtEnd = g_record["GUID"].value // datafield endDate
def iID = g_record["GUID"].value // datafield (PK) (S) ID
use (groovy.time.TimeCategory)
{
def duration = dtEnd - dtStart
def stmt = g_dbQuery.prepare(conn, "UPDATE DATAGROUP('<DATAGROUP_GUID>') SET <COLUMN_DURATION> = ? WHERE LID = ?")
stmt.setInt(1, duration.days)
stmt.setInt(2, iId)
stmt.executeUpdate()
stmt.close()
}
2.10.3. ISO-Datumsstring parsen
Parst eine Zeichenkette im ISO-Format in ein java.util.Date-Objekt.
import de.uplanet.lucy.server.mail.GroovyMailBuilder
def mail = new GroovyMailBuilder().composeMail {
from = "sender@example.org"
to = "recipient@example.org"
subject = "Insert the subject here"
body << "Hello world"
}
mail.drop()
Bitte beachten Sie: Das Versenden der E-Mail ist nicht Teil der Transaktion, sondern wird sofort und unabhängig vom Erfolg der Transaktion ausgeführt.
Snippet
def strFromAddr = g_session?.user?.emailBiz
def strFromName = g_session?.user?.name
def strToAddr = "" // insert the recipient here
new AntBuilder().mail(mailhost:"localhost", messagemimetype:"text/plain", subject:"Hello World") {
from(address:"${strFromName} <${strFromAddr}>")
to(address:addrTo)
message("""Here goes the message text.
With kind regards
${strFromName}
""")
}
2.12. Dateien und Verzeichnisse
2.12.1. Festplattenplatz ermitteln
Ermittelt die freie und gesamte Festplattenkapazität.
Snippet
// the partition where the Intrexx portal resides
File partition = new File(".")
long totalSpace = partition.totalSpace
long freeSpace = partition.freeSpace
Zugriff auf ein temporäres Prozess-Verzeichnis.
Das Verzeichnis ist auch für nachfolgende Prozess-Objekte sichtbar.
Es wird gelöscht, sobald der Prozess vollständig abgearbeitet wurde.
Fügt eine Datei zu einem bestehenden Datensatz hinzu. Mit copyFileToIntrexx(...) wird die Quelldatei
kopiert und bleibt an ihrem Speicherort erhalten. Ein analoger Aufruf ist mit moveFileToIntrexx(...).
Hierbei wird die Quelldatei nach Intrexx verschoben.
Parameter:
p_ctx - Der aktuelle Verarbeitungskontext (g_context)
p_fileSrc - Datei, die hinzugefügt werden soll
p_strFieldGUID - GUID des Dateidatenfeldes
p_recId - ID des Datensatzes, zu dem die Datei hinzugefügt werden soll
p_bTriggerWorkflow - Soll ein Prozess getriggert werden, der auf Datensatzänderungen reagiert?
Parameter:
p_ctx - Der aktuelle Verarbeitungskontext (g_context)
p_strFieldGUID - GUID des Dateidatenfeldes
p_recId - ID des Datensatzes, von dem die Datei gelöscht werden soll
Schreibt eine Textausgabe in eine Textdatei mit dem definierten Encoding.
Beispiel
def fileOut = new File("out.txt")
def strOutput = "This is my output text.\n"
fileOut.withWriter("UTF-8")
{
out -> out << strOutput
out.write(strOutput)
out.append(strOutput)
}
Snippet
def fileOut = new File("out.txt")
fileOut.withWriter("UTF-8")
{
out ->
//write output to file
}
g_om.createUser {
container = "System"
name = "user-${now().withoutFractionalSeconds}"
loginName = "UserU-${now().withoutFractionalSeconds}"
password = "secret"
emailBiz = "user@example.org"
description = "User created with Groovy at ${now().withoutFractionalSeconds}"
}
2.14.2. Benutzer anlegen
Snippet
// provide the copy of an user image (optional)
def fileTemplImage = new File(g_dirWorkflow, "user.jpg")
def fileUserImage = new File(g_dirWorkflowTmp, "user.jpg")
de.uplanet.io.IOHelper.copyFile(fileUserImage, fileTemplImage)
def user = g_om.createUser {
container = "System"
name = "user-${now().withoutFractionalSeconds}"
loginName = "UserU-${now().withoutFractionalSeconds}"
password = "secret"
emailBiz = "user@example.org"
description = "User created with Groovy at ${now().withoutFractionalSeconds}"
nickname = "dodo" // this is a custom user field
userImageFile = fileUserImage
// provide a list of sets (group, role, dist list, ...) the user should be member of
// allowed are GUIDs, unique names, paths, or org structure set nodes
memberOf = ["importantRole", "36B3BFD54A57BE5D1EE51288D920CDA9B20A67A4"]
}
// create a new password and send it to the user's emailBiz address (optional)
g_om.generateAndSendPassword(user, g_defaultLanguage)
2.14.3. GUIDs klassifizieren
Klassifizieren von GUIDs nach
Benutzer
Container (Organization, Organizational Unit, ...)
Set (Gruppe, Rolle, DistList, ...)
nicht klassifizierbare GUID
Snippet
def classified = g_om.classifyGuids(/* a list of GUIDs or text that contains GUIDs */)
// do something with the classified GUIDs
classified.users
classified.containers
classified.sets
classified.unclassified
2.15. Kategorien
2.15.1. Datum / Uhrzeit
Snippet
use (groovy.time.TimeCategory)
{
}
2.15.2. IValueHolder
Snippet
use (de.uplanet.lucy.server.scripting.groovy.GroovyIntrexxValueHolderCategory)
{
}
Bitte beachten Sie, dass vor allen Aktionen, die von Benutzern ausgelöst werden können,
eine Rechteprüfung (IxAccessController) erforderlich ist.
Snippet
response.json()
// define an error handler
response.onError =
{
e, err ->
//err.type = "default"
// either title/description, ...
err.title = "my error"
err.description = e.message
err.showEmbedded = true
// ... or a redirect
// err.redirectUrl = "https://www.example.org/"
err.redirectDelay = 1500 // milliseconds
}
// check permissions
g_permissions.check
{
// application("${application.guid}": "access")
// dataGroup("<data group GUID>": "read", "<another data group GUID>": "write,create")
}
// create some JSON content
writeJSON("person": [
givenName: "Donald",
lastName: "Duck",
age: 78,
nephews: ["Huey", "Dewey", "Louie"]
])
Mögliche Varianten des oben angegebenen Skripts
Closure ohne oder mit genau einem Parameter
Falls die Closure einen Parameter deklariert, wird im ersten Parameter (e) die aufgetretene Exception an die Closure übergeben.
Snippet
// define an error handler
response.onError = {e ->
writeJSON("error": "Something bad happened.")
}
Closure mit zwei Parametern
Im ersten Parameter (e) wird die aufgetretene Exception und im zweiten Parameter (err) ein
ErrorResponseData-Objekt
an die Closure übergeben. In der Closure kann das ErrorResponseData-Objekt gemäß den jeweiligen Bedürfnissen konfiguriert werden.
Snippet
// define an error handler
response.onError = {e, err ->
//err.type = "default"
// either title/description, ...
err.title = "my error"
err.description = e.message
err.showEmbedded = true
// ... or a redirect
// err.redirectUrl = "https://www.example.org/"
// err.redirectDelay = 1500 // milliseconds
}
Mit String
Der angegebene String wird im Response-Body zum Client gesendet.
Snippet
response.onError = '{"error": "Something bad happened."}'
Zuweisung eines anderen Objekts
Im Falle einer JSON-Antwort wird versucht, aus dem Objekt JSON zu erzeugen.
Falls die Antwort nicht vom Typ JSON ist, wird versucht, das Objekt in geeigneter Weise als Text auszugegeben.
Snippet
response.onError = [
"error": "Something bad happened.",
"solace": "But things could be worse."
]
12.19. Velocity
2.19.1. Text aus Velocity-Template erzeugen
import de.uplanet.lucy.server.scripting.velocity.VelocityContextUtil
import org.apache.velocity.app.Velocity
def fileVm = new File(g_dirWorkflow, "") // the Velocity input file
def vc = VelocityContextUtil.createDefaultContext(g_context)
// add additional variables to the Velocity context
// vc.put("PreparedQuery", g_dbQuery)
// vc.put("variableName", variableValue)
def template = Velocity.getTemplate(fileVm.path)
def writer = new StringWriter(4096) // 4 KiB initial buffer
template.merge(vc, writer)
g_log.info(writer.toString())
2.19.2. Datei aus Velocity-Template erzeugen
Aus Sicherheitsgründen können Velocity-Dateien nur ausgeführt werden, wenn sie sich in einem der folgenden Unterverzeichnisse befinden:
Schreibt einen INFO-Eintrag in die portal.log-Datei. Diese Methode kann verwendet werden,
wenn die zum Ausführungskontext des Skripts gehörige Logdatei nicht die portal.log ist,
die Ausgabe aber dennoch in die portal.log erfolgen soll.
Schreibt einen WARN-Eintrag in die portal.log-Datei. Diese Methode kann verwendet werden,
wenn die zum Ausführungskontext des Scripts gehörige Logdatei nicht die portal.log ist,
die Ausgabe aber aber dennoch in die portal.log erfolgen soll.
Schreibt einen ERROR-Eintrag in die portal.log-Datei. Diese Methode kann verwendet werden,
wenn die zum Ausführungskontext des Scripts gehörige Logdatei nicht die portal.log ist,
die Ausgabe aber aber dennoch in die portal.log erfolgen soll.
import de.uplanet.lucy.server.monitor.log.GroovyLogReader
// flush queued log entries to disk
GroovyLogReader.flushLogQueue()
// collect the log files
def logFiles = []
new File("internal/statistics").eachFile {
if (!it.name.startsWith(".")) // TODO check additional criteria
logFiles << it
}
// read the selected log files
logFiles.each { file ->
GroovyLogReader.readLog(file) { entry ->
// TODO do something with the entry
println("Time in millis = ${entry.time}, targetGuid = ${entry.targetGuid}")
}
}
2.23. Connector für Microsoft Exchange
2.23.1. Aktuelle Exchange-Verbindung
Liefert die aktuelle Verbindung zu Microsoft Exchange.
Schreibt den Text der Abwesenheitsnachricht und setzt den Status auf aktiv.
Achtung: Der Text wird sowohl als interne als auch als externe Nachricht gesetzt.
Snippet
import de.uplanet.lucy.server.businesslogic.exchange.util.ExchangeUtils
import de.uplanet.lucy.server.businesslogic.exchange.util.ExchangeConnectionUtil
def connEx = ExchangeConnectionUtil.getConnectionForWorkflowAction(g_context)
def mailboxUtil = ExchangeUtils.getMailboxUtil(connEx)
mailboxUtil.setOutOfOfficeMessage("Out of office till 2010/31/12")
mailboxUtil.setOutOfOffice(true)
Legt für den aktuellen Exchange-Benutzer einen neuen Termin an.
Parameter:
dtStartDate - Startdatum des Termins
dtEndDate - Enddatum des Termins
strSubject - Titel des Termins
strBody - Beschreibung des Termins
Werden nach dem Erstellen des Termins weitere Eigenschaften über set()-Methoden definiert,
müssen abschließend mit appointment.save() der Termin erneut gespeichert werden, um die Änderungen zu übernehmen.
Legt für den aktuellen Exchange-Benutzer einen neuen Kontakt an.
Parameter:
strLastName - Nachname des Kontakts
strFirstName - Vorname des Kontakts
strMail - E-Mail-Adresse des Kontakts
strMailbox - Mailbox des Benutzers, zu dem der Kontakt angelegt werden soll.
Wird null angegeben, wird die Mailbox des aktuellen Benutzers verwendet.
Werden nach dem Erstellen des Kontakts weitere Eigenschaften über set()-Methoden definiert,
muss der Termin abschließend mit contact.save() erneut gespeichert werden, um die Änderungen zu übernehmen.
Generiert eine neue E-Mail für den aktuellen Exchange-Benutzer.
Parameter:
strFrom - Absenderadresse
strTo - Empfängeradresse
strSubject - Betreff
strBody - Nachrichtentext
Werden nach dem Erstellen der E-Mail weitere Eigenschaften über set()-Methoden definiert,
muss der Entwurf abschließend mit message.save() erneut gespeichert werden, um die Änderungen zu übernehmen.
2.24.1. Portlet nur anzeigen, wenn Datensätze in Tabelle enthalten sind
Mit dem folgenden Skript wird das Portlet nur angezeigt, wenn die darin enthaltene Tabelle Datensätze enthält
und die Einstellung "Anzeige des Portlets im Web durch Groovy-Skript einschränken" gesetzt ist.
Das Skript kann genauso für die Einstellung "Auswahl des Portlets im Web durch Groovy-Skript einschränken"
verwendet werden - dann ist das Portlet nicht mehr in den Portlet-Einstellungen unter "Portlets aus Applikationen" aufgeführt
und kann damit nicht auf der Portalseite eingebunden werden.
2.24.2. Einschränkung von Portlets im Portletcontainer
Um Portlets im Portletcontainer einzuschränken,
muss als Rückgabewert eine Liste mit Portlet-Objekten zurückgegeben werden. Mit "g_portletPool" können alle verfügbaren Portlet-Objekte abgerufen werden.
In diesem Beispiel würde nur das Portlet mit der GUID zur Verfügung stehen, die anstatt dem Platzhalter eingetragen wird.
Wird ein Groovy-Endpoint aufgerufen, ohne dass der Client eine gültige Session-ID mitschickt, so wird auf dem Server implizit eine anonyme Session erzeugt.
Mit dem folgenden Skript kann verhindert werden, dass diese Sessions bis zum Timeout der anonymen Session auf dem Server bestehen bleiben.
Dabei ist das Kriterium für den automatischen Logout, dass der Client kein co_SId-Session-Cookie gesendet hat.
Snippet
import de.uplanet.server.transaction.TransactionManager
// if the client did not send a session cookie we logout
// the session after the current transaction has finished
if (!g_request.get('co_SId'))
TransactionManager.addAfterCommitAction {g_session.logout()}
Erzeugt einen ValueHolder für einen einfachen Datentyp.
Wird null übergeben, so wird ein NullValueHolder erzeugt. Dessen Wert null ist; hasValue() gibt false zurück.
Snippet
vh()
2.33. GUIDs parsen
GUIDs aus textuellen Eingaben parsen. Es sind mehrere Parameter möglich.