FORMCYCLE deploy-plugin plugin
This is a plugin for deploying plugin to Xima® Formcycle, hence the name FORMCYCLE deploy-plugin plugin.
The deploy plugin lets you upload and install plugins to Xima® Formcycle automatically. Compared with a manual installation via the backend menu, this offers several advantages:
- Plugin developers can integrate the deployment process into the Maven build process. This allows for faster testing, rapid development and does not necessitate a context switch that might slow down developers.
- It allows the installation of Xima® Formcycle tob e automated even further.
You can install the deploy plugin both as a client as well as a system plugin. If the former, you can only modify plugin of that cilent. It contains a servlet action for sending a plugin JAR file via an HTTP POST request. Depending on the other HTTP parameters, the plugin is either installed, updated, or deleted.
The uploaded plugin may already exist in the system. In this this, you usually want to update plugin - not have it installed twice. This requires a way to identify whether a plugin exists already. The servlet action allows for four different possibilities:
- (recommended) The plugin is identified based on an entry in its manifest. The manifest needs to be located at META-INF/MANIFEST.MF in the plugin JAR file, such as the group ID or artifact ID. Make sure you prepare the JAR file properly when building the plugin. This method is slightly harder to setup, but offers the advantage that the identifier always remains the same and does not depend on the file name or some internal ID.
- The plugin is identified based on its name, i.e. the file name of the upload JAR file. This is also the name as it is shown in the plugin menu.
- The plugin is identified based on its internal database ID. This ID is not shown in the UI currently and should only be used by developers.
- The plugin is identified based on its UUID. This ID is not shown in the UI currently and should only be used by developers.
By default, a servlet action is accessible to everybody. Usually, you do not want anonymous users to modifying the installed plugins. To secure the servlet, you can specify a password in the plugin configuration. You then need to include th
Standardmäßig ist eine Servlet-Aktion für alle frei zugänglich. Da es in der Regel unerwünscht ist, dass jeder (auch unangemeldete) Nutzer Plugins installieren kann, kann das Deploy-Plugin durch ein Passwort abgesichert werden. Dazu muss in der Plugin-Konfiguration der Passwort-Hash hinterlegt werden und das Passwort dann im HTTP-POST-Request mitgesendet werden.
Plugin-Konfiguration
Am Plugin selber kann konfiguriert werden, ob das Deploy-Servlet durch ein Passwort geschützt werden soll. Dieses Passwort muss dann im Klartext beim HTTP-POST-Request mit angegeben werden.
Zur Konfiguration des Passworts gibt es die eine Plugin-Eigenschaft token, diese hat das folgende Format
Folgende Hash-Methoden stehen zur Verfügung:
- plain
- Identitätsfunktion, das Passwort im Klartext angegeben.
- sha256
- SHA-256-Algorithmus.
- sha384
- SHA-384-Algorithmus.
- sha512
- SHA-512-Algorithmus.
Um das Passwort im Klartext beispielsweise auf admin festzulegen, wird der folgende Wert für die Plugin-Eigenschaft token eingegeben:
Um das Passwort mit SHA-256 beispielsweise auf admin festzulegen, wird der folgende Wert für die Plugin-Eigenschaft token eingegeben:
Der Hash ist gesalzen. Ein gültiger Hash für ein bestimmtes Passwort kann mit dem create-token-Servlet erzeugt werden, siehe unten.
Deploy-Servlet
Im Folgenden wird der Aufbau des HTTP-Requests beschrieben, um ein Plugin zu installieren, zu aktualisieren oder zu löschen.
Es muss immer ein HTTP-Post-Request verwendet werden und sich an folgende URL richten (Namen des FORMCYCLE-Servers entsprechend anpassen):
Die client-id muss nicht angegeben werden, wenn das Plugin als System-Plugin installiert ist.
Request-Parameter
Die Parameter können direkt als URL-Parameter, als multipart/form-data oder als application/x-www-form-urlencoded übergeben werden. Folgende Parameter werden vom Deploy-Plugin unterstützt und können übergeben werden:
- deploy-action
- Aktion, welche mit dem Plugin durchgeführt werden soll. Erlaubte Werte sind save, update-properties, activate, deactivate und delete. Ein Erklärung zu diesen Aktionen findet sich unten.
- client-id
- ID des Mandanten, in dem ein Plugin installiert, aktualisiert oder gelöscht werden soll. Es darf nur entweder client-id oder client-uuid angegeben werden
- client-uuid
- UUID des Mandanten, in dem ein Plugin installiert, aktualisiert oder gelöscht werden soll. Es darf nur entweder client-id oder client-uuid angegeben werden. Es ist zu beachten, dass der Aufruf eines als Mandant-Plugin installierten Servlet-Aktion immer der Parameter client-id erforderlich ist.
- jar-file
- Binärdaten mit der JAR-Datei des Plugins, welches aktualisert oder installiert werden soll.
- token
- Das Token (Password) für die Authorisierung des Requests. Nur erforderlich, wenn in der Plugin-Konfiguration ein Token festgelegt wurde.
- plugin-ident
- Die Art, wie nach einem vorhandenen Plugin gesucht wird (siehe oben). Folgende Werte sind erlaubt:
- manifest
- Identifiziert ein Plugin anhand eines Eintrags im Manifest.
- id
- Identifiziert ein Plugin anhand seiner Datenbank-ID.
- name
- Identifiziert ein Plugin anhand seines Namens (Dateiname der JAR-Datei)
- uuid
- Identifiziert ein Plugin anhand seiner UUID.
- plugin-identifier
- Identifikator des Plugins, welches aktualisiert oder gelöscht werden soll. Die konkrete Bedeutung dieses Parameters ist abhängig von dem Wert von plugin-ident:
- plugin-ident=manifest
- plugin-identifier muss den Namen der Manifest-Eigenschaft und dessen Wert enthalten, im Format ATTRIBUTE_NAME=VALUE. Wird zum Beispiel Implementation-Title=com.example.fc.plugin:my-plugin übergeben wird, wird nach einem existierenden Plugin gesucht, welches im Manifest in der Eigenschaft Implementation-Title den Wert com.example.fc.plugin:my-plugin stehen hat.
- plugin-ident=id
- plugin-identifier muss die gewünschte ID des Plugins enthalten, etwa 53 oder /893.
- plugin-ident=name
- plugin-identifier muss den gewünschten Names des Plugins enthalten, etwa my-plugin.jar oder /foobar.jar.
- plugin-ident=uuid
- plugin-identifier muss die gewünschte UUID des Plugins enthalten, etwa 03022599-903d-429b-9822-80a324a542fc.
Andernfalls wird das Plugin installiert, falls noch nicht vorhanden, oder aktualisiert, falls vorhanden.
- clear-properties
- Entweder true oder false. Wenn true, werden alle Plugin-Eigenschaften entfernt beziehungsweise deren Werte geleert. Dies wird ausgeführt, bevor die neu zu setzenden Plugin-Eigenschaften (Parameter /property) angewendet werden.
- property
- Name und Wert einer Plugin-Eigenschaft, die an der Plugin-Konfiguration gesetzt werden soll, im Format key=value. Dieser HTTP-Parameter kann mehrfach angegeben werden, um mehrere Plugin-Eigenschafte zu setzen. Wird etwa database.username=max übergeben, wird die Plugin-Eigenschaft database.username auf max gesetzt.
- disallow-install
- Entweder true oder false. Ist diese Option auf true gesetzt und existiert das Plugin noch nicht (bezüglich der angegebenen plugin-ident und plugin-identifier), wird das Plugin nicht neu installiert und eine Fehlermeldung zurückgegeben. ; locale
- Die Sprache, welche während der Installation, Aktualisierung oder Löschung des Plugins verwendet werden soll, etwa en oder de. Beeinflusst nur einige Fehlermeldungen und kann in der Regel weggelassen werden.
Deploy-Action
Der Wert des Parameters deploy-action gibt an, was genau mit dem Plugin geschehen soll. Es gibt dabei die folgenden Möglichkeiten:
- save
- Überträgt das angegebene Plugin auf das FORMCYCLE-System. Es muss hierbei eine JAR-Datei übertragen werden. Falls das Plugin noch nicht existiert (und der Parameter disallow-install nicht gesetzt ist), wird das Plugin neu installiert und ist dann aktiviert. Andernfalls, falls das Plugin bereits existiert, wird es aktualisiert, dabei bleibt das Plugin aktiviert oder deaktiviert.
curl -X POST \
-F deploy-action=save \
-F token=admin \
-F plugin-ident=manifest \
-F plugin-identifier=Implementation-Title=com.example:plugin \
-F "jar-file=@my-plugin.jar" \
"http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
- delete
- Löscht das angegebene Plugin. Es darf hierbei keine JAR-Datei übertragen werden. Existiert das angegebene Plugin nicht, wird ein Fehler zurückgegeben. Beispiel:
curl -X POST \
-F deploy-action=delete \
-F token=admin \
-F plugin-ident=manifest \
-F plugin-identifier=Implementation-Title=com.example:plugin \
"http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
- activate
- Aktiviert das angegebene Plugin. Es darf hierbei keine JAR-Datei übertragen werden. Existiert das angegebene Plugin nicht, wird ein Fehler zurückgegeben. Ist das Plugin bereits aktiviert, wird nicht getan und ein Erfolg zurückgegeben. Beispiel:
curl -X POST \
-F deploy-action=activate \
-F token=admin \
-F plugin-ident=manifest \
-F plugin-identifier=Implementation-Title=com.example:plugin \
"http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
- deactivate
- Deaktiviert das angegebene Plugin. Es darf hierbei keine JAR-Datei übertragen werden. Existiert das angegebene Plugin nicht, wird ein Fehler zurückgegeben. Ist das Plugin bereits deaktiviert, wird nicht getan und ein Erfolg zurückgegeben. Beispiel:
curl -X POST \
-F deploy-action=deactivate \
-F token=admin \
-F plugin-ident=manifest \
-F plugin-identifier=Implementation-Title=com.example:plugin \
"http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
- update-properties
- Aktualisiert die Eigenschaften des angegebenen Plugins. Es darf hierbei keine JAR-Datei übertragen werden. Entweder die Eigenschaft clear-properties oder property sollte gesetzt sein. Existiert das angegebene Plugin nicht, wird ein Fehler zurückgegeben. Beispiel:
curl -X POST \
-F deploy-action=update-properties \
-F token=admin \
-F plugin-ident=manifest \
-F plugin-identifier=Implementation-Title=com.example:plugin \
-F clear-properties=false \
-F property=foo=bar \
"http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
Response
Das Deploy-Plugin liefert einen Statuscode und ein JSON-Objekt mit den Details zurück. Der Status-Code ist 2xx, falls das Deploy-Plugin erfolgreich ausgeführt wurde.
Das JSON-Objekt hat dabei die folgende Struktur:
"$schema": "http://json-schema.org/schema",
"description": "Represents the response of the deploy plugin servlet.",
"required": [
"success",
"statusCode",
"details",
"message",
"requestParameters"
],
"properties": {
"success": {
"type": "boolean",
"title": "Success status",
"description": "true if the deploy plugin servlet was executed successfully, or false otherwise"
},
"statusCode": {
"type": "number",
"title": "HTTP status code",
"description": "The status code of the HTTP request that contains this response."
},
"details": {
"type": "object",
"title": "Result details",
"description": "Detailed information about the plugin processed by the deploy plugin servlet.",
"oneOf": [
{
"description": "If the deploy plugin servlet was successful, details about the successfully executed action.",
"required": [
"id",
"uuid",
"name",
"active",
"message"
],
"properties": {
"id": {
"type": "number",
"title": "Plugin ID",
"description": "The database ID of the processed plugin."
},
"uuid": {
"type": "string",
"title": "Plugin UUID",
"description": "The UUID of the processed plugin."
},
"name": {
"type": "string",
"title": "Plugin name",
"description": "The name of the processed plugin, i.e. the file name of the plugin JAR file."
},
"active": {
"type": "boolean",
"title": "Plugin activation status",
"description": "true if the plugin is now active, false if it is now inactive."
},
"message": {
"type": "string",
"title": "Result message",
"description": "Human-readable message describing the performed action."
}
}
},
{
"required": [
"exceptionType",
"exceptionMessage"
],
"description": "If the deploy plugin servlet was unsuccessful, details about the error that occurred.",
"properties": {
"exceptionType": {
"type": "string",
"title": "Exception type",
"description": "The type of the error that occurred, a fully-classified name of the Java exception class."
},
"exceptionMessage": {
"type": "string",
"title": "Exception message",
"description": "The human-readable message of the error that occurred."
}
}
}
]
},
"message": {
"type": "string",
"title": "Result message",
"description": "A human-readable message that describes this result."
},
"requestParameters": {
"type": "object",
"title": "Request parameters",
"description": "The parameters of the request that triggered this response."
}
}
}
Beispiel für die Antwort beim Aktualisieren eines Plugins:
"success": true,
"requestParameters": {
"plugin-ident": ["manifest"],
"name": ["deploy-plugin"],
"client-id": ["1"],
"deploy-action": ["save"],
"plugin-identifier": ["Implementation-Title=com.example:plugin"],
"token": ["admin"]
},
"details": {
"name": "my-plugin.jar",
"active": true,
"id": 203,
"message": "Plugin saved successfully.",
"uuid": "2fe3e1ba-cb32-434e-9f59-4422f8dabcad"
},
"message": "Plugin saved successfully.",
"statusCode": 200
}
Beispiel für die Antwort beim Löschen, falls das angegebene Plugin nicht gefunden wurde:
"success": false,
"requestParameters": {
"plugin-ident": ["manifest"],
"name": ["deploy-plugin"],
"client-id": ["1"],
"deploy-action": ["delete"],
"plugin-identifier": ["Implementation-Title=com.example:plugin"],
"token": ["admin"]
},
"details": {
"exceptionType": "java.lang.IllegalArgumentException",
"exceptionMessage": "Deploy action 'delete' requires an existing pluign, but none was found."
},
"message": "class java.lang.IllegalArgumentException: Deploy action 'delete' requires an existing pluign, but none was found.",
"statusCode": 404
}
Create-Token-Servlet
Mit diesem Servlet kann ein Hash für ein bestimmtes Klartextpasswort erzeugt werden, welcher dann in der Plugin-Eigenschaft token hinterlegt werden kann. Es muss hierbei ein HTTP-GET-Request verwendet werden (Pfad auf den FORMCYCLE-Servet und die Mandant-ID entsprechend ersetzen):
- token
- Der Klartext des Passwort, zu dem ein Hash ermittelt werden soll.
- method
- Methode zum Berechnen des Hashes. Erlaubte Werte sind plain, sha256, sha384 und sha512. Optional, Standardwert ist sha256.
Als Antwort wird ein JSON zurückgeliefert, welches das gleiche Format wie die Antwort des Deploy-Plugins hat. Beispiel für eine Antwort:
"success": true,
"requestParameters": {
"name": ["create-token"],
"client-id": ["1"],
"token": ["admin"]
},
"details": {
"method": "sha256",
"token": "sha256:S+32GI3fWXwHHulUMtWmjpQ15EqMvgVYguuO9SKxfNw+ckAGQljP6tKlf1EITnU7"
},
"message": "Hash token created successfully",
"statusCode": 200
}
Maven-Deploy-Plugin
Um ein Plugin nach dem Bauen über Maven in FORMCYCLE hochzuladen, gibt es auch ein Maven-Plugin, welches das Deploy-Servlet anspricht. Dieses ist über die Artifactory von XIMA erhältlich, falls man die entsprechenden Rechte hierfür hat:
Konfiguration
<groupId>de.xima.fc.maven.plugin</groupId>
<artifactId>fc-deploy-plugin-maven-plugin</artifactId>
<version>1.1.0</version>
<configuration>
<url>http://localhost:8080/formcycle</url>
<pluginName>deploy-plugin</pluginName>
<clientId>52</clientId>
<token>admin</token>
<deployAction>save</deployAction>
<pluginIdent>name</manifest>
<pluginIdentifier>my-plugin.jar</pluginIdentifier>
<jarFile></jarFile>
<disallowInstall>false</disallowInstall>
<locale>en</locale>
<clearProperties>true</clearProperties>
<properties>
<property1>value1</property1>
<property2>value2</property2>
<properties>
</configuration>
</plugin>
Das Plugin hat die folgenden Optionen zur Konfiguration:
- url [Standardwert: ${fcDeployUrl}]
- URL mit Kontextpfad zum FORMCYCLE-Server, etwa http://localhost:8080/formcycle
- pluginName [Standardwert: deploy-plugin]
- Der Name des Deploy-Plugins für den URL-Parameter name. In der Regel muss diese Option nicht gesetzt werden, der Standardwert ist ausreichend.
- clientId [Standardwert: ${fcDeployClientId}]
- ID des Mandanten, für den das Plugin installiert, aktualisiert oder gelöscht werden soll. Entspricht dem Parameter client-id des Deploy-Plugins, siehe oben.
- clientUuid
- Alternative zu clientID. UUID des Mandanten, für den das Plugin installiert, aktualisiert oder gelöscht werden soll. Entspricht dem Parameter client-uuid des Deploy-Plugins, siehe oben.
- token [Standardwert: ${fcDeployToken}]
- Passwort für das Servlet-Plugin, falls in der Konfiguration des Deploy-Plugins ein Passwort gesetzt wurde.
- deployAction [Standardwert: save]
- Aktion, welche mit dem Plugin durchgeführt werden soll. Erlaubte Werte sind save, update-properties, activate, deactivate und delete. Entspricht dem Parameter deploy-action des Deploy-Plugins, siehe oben.
- pluginIdent [Standardwert: manifest]
- Die Art, wie nach einem vorhandenen Plugin gesucht wird. Entspricht dem Parameter plugin-ident des Deploy-Plugins, siehe oben.
- pluginIdentifier [Standardwert: Implementation-Title=${project.groupId}:${project.artifactId}]
- Identifikator des Plugins, welches aktualisiert oder gelöscht werden soll. Entspricht dem Parameter plugin-identifier des Deploy-Plugins, siehe oben.
- jarFile [Standartwert: Haupt-Build-Artifakt des Maven-Projekts]
- Pfad zur JAR-Datei, die hochgeladen werden soll, relativ zum Basisverzeichnis des Maven-Projekts.
- disallowInstall [Standardwert: false]
- Wenn true und das Plugin noch nicht existiert, wird abgebrochen und ein Fehler zurückgegeben. Entspricht dem Parameter disallow-install des Deploy-Plugins, siehe oben.
- locale [Standardwert: en]
- Sprache, die für die Installation, Aktualisierung oder Löschung des Plugins genutzt wird. Entspricht dem Parameter locale des Deploy-Plugins, siehe oben.
- clearProperties [Standardwert: false]
- Löscht die Werte aller Plugin-Eigenschaften. Entspricht dem Parameter clear-properties des Deploy-Plugins, siehe oben.
- properties
- Key-Value-Paare mit Eigenschaften, die an dem Plugin gesetzt werden sollen. Entspricht dem Parameter clear-properties des Deploy-Plugins, siehe oben.
Empfehlung für Plugin-Projekt
Während das Plugin zahlreiche Einstellunsgmöglichkeiten anbietet, reichen meist die Standardwerte aus. Empfohlen wird das folgende Vorgehen bei der Entwicklung von Plugin-Projekten.
Folgendes Schnippsel sollte in der Profil-Sektion der pom.xml eingefügt werden:
<fc-deploy-plugin-maven-plugin.version>1.1.0</fc-deploy-plugin-maven-plugin.version>
</properties>
<profiles>
<profile>
<id>fc-deploy</id>
<activation>
<property>
<name>fcDeployUrl</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>de.xima.fc.maven.plugin</groupId>
<artifactId>fc-deploy-plugin-maven-plugin</artifactId>
<version>${fc-deploy-plugin-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Das Plugin wird dann anhand des Eintrags Implementation-Title im Manifest identifiziert. Hierzu muss der Wert korrekt im Manifest gesetzt werden. Dies kann entweder über das maven-jar-plugin oder über das maven-assembly-plugin geschehen, je nachdem, welches von diesen im Plugin-Projekt genutzt wird:
<xfc.version>6.4.0-SNAPSHOT</xfc.version>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<maven-assembly-plugin.version>3.2.0</maven-assembly-plugin.version>
</properties>
<build>
<plugins>
<!-- If using the maven-jar-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<outputDirectory>${basedir}</outputDirectory>
<finalName>${project.artifactId}</finalName>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<formcycle-version-requirement>${xfc.version}</formcycle-version-requirement>
<Implementation-Title>${project.groupId}:${project.artifactId}</Implementation-Title>
<Implementation-Vendor-Id>${project.groupId}</Implementation-Vendor-Id>
<Implementation-Version>${project.version}</Implementation-Version>
<Build-Timestamp>${maven.build.timestamp}</Build-Timestamp>
</manifestEntries>
</archive>
</configuration>
</plugin>
<!-- If using the maven-assembly-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<executions>
<execution>
<id>fat-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<outputDirectory>${basedir}</outputDirectory>
<finalName>${project.artifactId}</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifestEntries>
<Build-Timestamp>${maven.build.timestamp}</Build-Timestamp>
<Implementation-Vendor-Id>${project.groupId}</Implementation-Vendor-Id>
<Implementation-Title>${project.groupId}:${project.artifactId}</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
<formcycle-version-requirement>${xfc.version}</formcycle-version-requirement>
</manifestEntries>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Nun kann das Plugin über Maven gebaut und hochgeladen werden. Die URL auf FORMCYCLE, die Mandant-ID und das Token (Passwort) wird dynamisch über Parameter an Maven übergeben:
Hinweis: IDE wie Eclipse und IntelliJ erlauben es, eine Build-Konfiguration für das Plugin-Projekt zu erstellen, wo die Parameter fcDeployUrl, fcDeployClientId und fcDeployToken hinterlegt werden können.