5.3. Kontakte anlegen über JSON-RPC

JSON RPC Requests werden als HTTP POST Requests gegen die URI "/json" des GREYHOUND Server HTTP Ports geschickt. Sie müssen die HTTP Header "Authorization" und "Content-Type" enthalten, sowie einen Request Body:
Die Authentifizierung erfolg über HTTP Basic Auth, wobei sich allerdings der Benutzername aus einer sogenannten "Client-ID" und dem GREYHOUND Benutzernamen zusammensetzt. Die Client-ID wird nachfolgend genauer beschrieben. Der Basic Auth Benutzername setzt sich aus der 32-stelligen Client-ID, einem Bindestrich ("Dash") und dem GREYHOUND Benutzernamen zusammen. Der gesamte HTTP Authorization Header sieht demnach wie folgt aus:
HTTP Header:
1
Authorization: Basic auth-str
Mit auth-str = base64( clientId + "-" + greyhoundUsername )
Die Client-ID ist ein 32-Zeichen langer String (z.B. ein MD5 Hash aus einem Zufalls-String). Sie repräsentiert eine Client-Session und sollte während eines Programmdurchlaufs gleich bleiben. Der GREYHOUND Server erlaubt pro Benutzer nur eine begrenzte Anzahl unterschiedlicher Client-Verbindungen - dazu zählen sowohl der GREYHOUND Client, als auch Unity, die Mobil-Clients und auch Aufrufe über die RPC Schnittstelle. Aus diesem Grund sollte eine Anwendung oder ein Skript, das über die JSON RPC Schnittstelle auf GREYHOUND zugreift, während einer Session immer dieselbe Client-ID verwenden, da es sonst passieren kann, dass nach einigen Aufrufen die maximale Anzahl unterschiedlicher Clients für den Benutzer erreicht ist und weitere Requests abgelehnt werden.
Die Client-ID dient hauptsächlich dazu, Element-Sperrungen pro Benutzer und Client korrekt zu handhaben. Schreibzugriffe auf Elemente erfordern eine Sperrung des Elements - d.h. das Element wird zunächst gesperrt, dann sind Schreibzugriffe möglich und anschließend wird das Element wieder entsperrt. Sperrt ein Benutzer über die RPC API ein Element, so gilt diese Sperrung nur für diesen Benutzer mit dieser Client-ID. Für die Schreibzugriffe (und auch das Entsperren) muss daher dieselbe Client-ID verwendet werden, wie beim Sperren des Elements.
Im Prinzip kann auch eine hardcodierte Client-ID verwendet werden, unabhängig von Benutzer oder Session. Hierbei ist zu beachten, dass dann alle Instanzen des Programms/Scripts für einen Benutzer Elemente schreiben und entsperren können, die von anderen Instanzen gesperrt wurden.
Da die HTTP Requests zustandslos sind, verfällt eine serverseitige Verbindung mit einem Client, sobald dieser länger als 60 Sekunden keinen Request mehr mit seiner Client-ID gesendet hat. Daher verfallen auch Elementsperrungen über die JSON Schnittstelle nach 60 Sekunden, wenn in dem Zeitraum keine weiteren Requests mit derselben Client-ID erfolgen.
JSON RPC Requests müssen mit dem Content-Type application/json gesendet werden. Das Charset kann optionalerweise mit angegeben werden, muss allerdings dann utf-8 sein.
HTTP Header:
1
Content-Type: application/json
Request Body
Der Request Body ist ein JSON String in UTF-8 Codierung, der ein Objekt mit den folgenden Properties darstellt (hier am Beispiel der RPC Funktion RpcGroups.GetList):
JSON:
1
2
3
4
5
6
7
8
{
  "version": "1.1",
  "method": "RpcGroups.GetList",
  "params": [
    false
  ],
  "id": 1
}
Die Property "version" ist für JSON RPC 1.1 fest vorgegeben (GREYHOUND unterstützt derzeit nur Version 1.1 des JSON RPC Formats) und die Property "id" ist optional. Wird er mitgesendet, so enthält die Antwort ebenfalls eine Property "id" mit demselben Wert, um so im Zweifelsfall eine Zuordnung der Antwort zum Request zu ermöglichen. Die Property "method" enthält den Namen der RPC Funktion (inkl. der Unit bzw. des Services) und die Property "params" enthält einen Array mit den Parametern des Funktionsaufrufs.
Die Antworten auf RPC Requests erfolgen ebenfalls im JSON-RPC Format. Dabei steht das Ergebnis des Funktionsaufrufs in der Eigenschaft "result":
JSON:
1
2
3
4
{
  "version":"1.1",
  "result": 123
}
Für Elemente ist der Service RpcItems (in der Unit "rpc_itemslib") zuständig. Für das Anlegen von Elementen wird die Funktion RpcItems.New verwendet, deren erster Parameter ein DetailedItem (das anzulegende Element) ist und der zweite Parameter ein Boolean, der angibt, ob das Element nach dem Anlegen sofort gesperrt werden soll (um z.B. weitere Schreibzugriffe darauf durchzuführen, bevor Regeln ausgeführt werden oder andere Benutzer das Element bearbeiten können).
Der Element-Typ wird durch die Property Kind festgelegt, z.B. 8 für Kontakte. Die Element-Typ-abhängigen Daten eines Elements werden in einer Untereigenschaft der Property Properties dargestellt. Diese enthält für jeden Element-Typ eine Eigenschaft, so dass z.B. die Daten für Kontakte, die nicht in anderen Element-Typen enthalten sind, in der Eigenschaft Properties.Contact stehen. Hier findet man z.B. Eigenschaften für Name, Firma, Kommunikationsadressen (ComLinks) usw.
Ein Kontakt lässt sich also z.B. mit folgendem HTTP Request anlegen:
HTTP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
POST /json HTTP/1.1
Content-Type: application/json
Authorization: Basic ...

{
  "version":"1.1",
  "method":"RpcItems.New",
  "params":
  [
    {
      "Kind": 8,
      "State": 1,
      "GroupRef": 1,
      "Priority": 2,
      "Subject": "John Doe",
      "Properties":
      {
        "Contact":
        {
          "Firstname": "John",
          "Lastname": "Doe",
          "ComLinks":
          [
            {
              "Category": 1,
              "Preferred": true,
              "Text": "<johndoe@test.com>"
            },
            {
              "Category": 1,
              "Kind": 2,
              "Text": "<Musterstraße 123, 12345 Musterhausen, Deutschland>"
            }
          ]
        }
      }
      "UserFields":
      [
        {
          "FieldRef": 6,
          "Value": "K-0815"
        }
      ]
    },
    false
  ]
}
Folgendes ist hierbei zu beachten:
Alle Eigenschaften, die nicht übergeben werden, interpretiert die RPC Schnittstelle als entsprechenden leeren Wert, also eine leere Zeichenkette für Strings, eine 0 für Integer, usw. Eigenschaften können also weggelassen werden, werden aber dennoch entsprechend interpretiert. Lässt man z.B. den Element-Typ (Kind) weg, so wird der Typ 0 (E-Mail) angenommen.
Im Beispiel wird der Element-Typ (Kind) wird auf 8 (für Kontakte) gesetzt, der Element-Status auf 1 (Neu). Beim Anlegen eines Elements muss zwingend eine Gruppe angegeben werden, in die das Element gelegt wird (GroupRef) und das Element muss einen Betreff erhalten (Subject). Um die ID einer Gruppe zu ermitteln, kann im GREYHOUND Client der ID Inspektor genutzt werden. Dieser findet sich im Menu "Funktionen" > "ID-Inspect". Es erscheint ein kleines Fenster, in das per Drag & Drop benutzerdefinierte Felder (aus der Liste in "Einstellungen" > "Benutzerdefinierte Felder"), Elemente, Gruppen usw. gezogen werden können. Der ID Inspektor zeigt dann die ID des entsprechenden Elements an. In den Kontakteigenschaften (Properties.Contact) werden Vor- und Nachname gesetzt (Firstname, Lastname), sowie Kommunikationsadresse (ComLinks): eine (bevorzugte) E-Mail Adresse (Kind 0, weggelassen) der Kategorie "Geschäftlich" (Category 1) und eine Postadresse (Kind 2) der Kategorie "Geschäftlich". Die Adressen werden jeweils als String in der Eigenschaft "Text" übergeben und stehen in spitzen Klammern (wie z.B. bei Adressen im E-Mail Standard üblich). Außerdem wird das benutzerdefinierte Feld mit der ID 6 auf den Wert "K-0815" gesetzt (z.B. um eine Kundennummer zu hinterlegen).
Der Rückgabewert des Aufrufs enthält die Element-ID des neu angelegten Kontakts in GREYHOUND:
JSON:
1
2
3
4
{
  "version":"1.1",
  "result":1001
}
Wenn Kontakte nicht nur einmalig, sondern regelmäßig importiert werden sollen, dann empfiehlt es sich, vor dem Anlegen zu prüfen, ob der entsprechende Kontakt bereits existiert. Hierzu kann im Quellsystem die GREYHOUND ID von Kontakten beim erfolgreichen erstellen hinterlegt werden. Alternativ kann man z.B. auch in GREYHOUND ein benutzerdefiniertes Feld anlegen und in dieses beim Erstellen des Elements die Kontakt-ID aus dem Quellsystem hinterlegen und dann beim Import zunächst prüfen, ob es bereits Elemente mit der ID in dem entsprechenden benutzerdefinierten Feld gibt. Dazu kann beispielsweise die Funktion RpcItems.GetList verwendet werden, die einen Such-Filter bereitstellt.