Wiki source code of FORMCYCLE-Deploy-Plugin-Plugin


Show last authors
1 [[**Plugin download**>>url:https://customer.formcycle.eu/index.php/apps/files/?dir=/FORMCYCLE%20-%20Plugins%20Customer/fc-plugin-deploy-plugin&fileid=12657||target="_blank"]] (requires login)
2
3 This is a plugin for deploying plugin to {{formcycle/}}, hence the name //FORMCYCLE deploy-plugin plugin//.
4
5 {{content/}}
6
7 The deploy plugin lets you upload and install plugins to {{formcycle/}} automatically. Compared with a manual installation via [[the backend menu>>doc:Formcycle.UserInterface.Client.Plugins]], this offers several advantages:
8
9 * 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.
10 * It allows the installation of {{formcycle/}} tob e automated even further.
11
12 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>>doc:Formcycle.PluginDevelopment.Types.IPluginServletAction]] 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.
13
14 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:
15
16 * (**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.
17 * 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>>doc:Formcycle.UserInterface.Client.Plugins]].
18 * 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.
19 * The plugin is identified based on its UUID. This ID is not shown in the UI currently and should only be used by developers.
20
21 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 this password in the HTTP POST request.
22
23 == Plugin configuration ==
24
25 You can optionally set a password for securing the access to the plugin deploy servlet. If you do, you need to include the password in the HTTP POST request to authorize that request.
26
27 Specify the token by entering a value for the plugin property //token//. It must be entered in the following format:
28
29 {{code language="none"}}
30 hash_method:hashed_value
31 {{/code}}
32
33 The following hash methods are available.
34
35 ; plain
36 : Identity function. Lets you enter a plain text password.
37 ; sha256
38 : SHA-256 algorithm.
39 ; sha384
40 : SHA-384 algorithm.
41 ; sha512
42 : SHA-512 algorithm.
43
44 To enter the password //admin// as plain text, use:
45
46 {{code language="none"}}
47 plain:admin
48 {{/code}}
49
50 To enter the password //admin// hashed with SHA-256, use:
51
52 {{code language="none"}}
53 sha256:S+32GI3fWXwHHulUMtWmjpQ15EqMvgVYguuO9SKxfNw+ckAGQljP6tKlf1EITnU7
54 {{/code}}
55
56 The hash is salted. You can generate a valid hash for a given password via the //create-token// servlet, see below.
57
58 == Deploy servlet ==
59
60 The following describes the structure of the HTTP request you need to adhere to in order to install, update, or delete a plugin.
61
62 The HTTP method must be POST, other methods will result in an error. The [[endpoint URL is as follows>>doc:Formcycle.PluginDevelopment.Types.IPluginServletAction]] (change the name of the FORMCYCLE server and the client ID):
63
64 {{code language="none"}}
65 POST http://localhost:8080/formcycle/plugin?name=deploy-plugin&client-id=154 HTTP/1.1
66 {{/code}}
67
68 The //client-id// is not required in case the plugin is installed as a system plugin.
69
70 === Request parameter ===
71
72 You can specify the parameters either directly as URL parameters, or as //multipart/form-data// or //application/x-www-form-urlencoded//. The following parameters are available and supported by the plugin deploy servlet:
73
74 ; deploy-action
75 : Action to be performed on the plugin. Allowed values are //save//, //update-properties//, //activate//, //deactivate// and //delete//. See below for a description of each method.
76 ; client-id
77 : ID of the client where the plugin is installed, updated, or deleted. You must specify only one of //client-id// or //client-uuid//.
78 ; client-uuid
79 : UUID of the client where the plugin is installed, updated, or deleted. You must specify only one of //client-id// or //client-uuid//. Please note that a plugin installed as a client plugin always required the parameter //client-id//.
80 ; jar-file
81 : Binary data of the JAR file with the plugin (required only when installing or updating the plugin).
82 ; token
83 : The token (password) for authorizing the request. Required only when the a token was set in the plugin configuration.
84 ; plugin-ident
85 : The method used for searching an already existing plugin, see above. The following methods are supported:
86 :; manifest
87 :: Identifies a plugin based on an entry in its manifest.
88 :; id
89 :: Identifies a plugin based on its database ID.
90 :; name
91 :: Identifies a plugin based on its name (the file name of the plugin JAR file).
92 :; uuid
93 :: Identifies a plugin based on its UUID.
94 ; plugin-identifier
95 : Identifier of the plugin that should be installed, updated, or deleted. The exact meaning of this parameter depends on the chosed //plugin-ident// method:
96 :; plugin-ident=manifest
97 :: //plugin-identifier// must contain the name of the manifest property and its value, in the format //Attribute-Name=value//. For example, if this property is set to //Implementation-Title=com.example.fc.plugin:my-plugin//, this will search for a plugin with a manifest entry //Implementation-Title// set to //com.example.fc.plugin:my-plugin//.
98 :; plugin-ident=id
99 :: //plugin-identifier// must contain the data base ID of the target plugin, such as //53// or //893//.
100 :; plugin-ident=name
101 :: //plugin-identifier// must contain the name of the target plugin, such as //my-plugin.jar// or //foobar.jar//.
102 :; plugin-ident=uuid
103 :: //plugin-identifier// must contain the UUID of the target plugin, such as //03022599-903d-429b-9822-80a324a542fc//.
104 ; clear-properties
105 : Either //true// or //false//. If set to //true//, all plugin property values are cleared. This is done before the new properties (see parameter //property//) are applied.
106 ; property
107 : Name and value of a plugin property to set, in the format //key=value//. This HTTP parameter may be specified multiple times if you want set multiple properties. For example, if set to //database.username=john//, this sets the plugin property //database.username// to //john//.
108 ; disallow-install
109 : Either //true// or //false//. When this is set to //true// and the plugin does not exists yet (as determined by the given //plugin-ident// and //plugin-identifier// parameters), the plugin is not installed and an error is returned. Otherwise, when set to //false//, the plugin is installed if it does not exists yet and updated if it does.
110 ; locale
111 : The language to be used when the plugin is modified, such as //en// or //de//. May affect some error messages. Usually this parameter is not neccessary.
112
113 === Deploy actions ===
114
115 The value of the parameter //deploy-action// specifies what should happen with the selected plugin. The following actions are available:
116
117 ; save
118 : Transmits the plugin to the {{formcycle/}} server. You need to specify a JAR file. If the plugin does not exists yet (and the parameters //disallow-install// is not set), the plugin is installed and activated. Otherwise, if the plugin exists already, it is only updated and left active or inactive. For example:
119
120 (((
121 {{code language="bash"}}
122 # Installs or updates the given plugin.
123 curl -X POST \
124 -F deploy-action=save \
125 -F token=admin \
126 -F plugin-ident=manifest \
127 -F plugin-identifier=Implementation-Title=com.example:plugin \
128 -F "jar-file=@my-plugin.jar" \
129 "http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
130 {{/code}}
131 )))
132
133 ; delete
134 : Deletes the given plugin. You must not specify a JAR file. If the specified plugin does not exist yet, an error is returned. For example:
135
136 (((
137 {{code language="bash"}}
138 # Löscht das Plugin mit dem Implementation-Title com.example:plugin
139 curl -X POST \
140 -F deploy-action=delete \
141 -F token=admin \
142 -F plugin-ident=manifest \
143 -F plugin-identifier=Implementation-Title=com.example:plugin \
144 "http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
145 {{/code}}
146 )))
147
148 ; activate
149 : Activates the given plugin. You must not specify a JAR file. If the specified plugin is already active, no action is performed an a success is returned. For example:
150
151 (((
152 {{code language="bash"}}
153 # Activates the given plugin
154 curl -X POST \
155 -F deploy-action=activate \
156 -F token=admin \
157 -F plugin-ident=manifest \
158 -F plugin-identifier=Implementation-Title=com.example:plugin \
159 "http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
160 {{/code}}
161 )))
162
163 ; deactivate
164 : Deactivates the given plugin. You must not specify a JAR file. If the specified plugin is already inactive, no action is performed an a success is returned. For example:
165
166 (((
167 {{code language="bash"}}
168 # Deactivates the given plugin
169 curl -X POST \
170 -F deploy-action=deactivate \
171 -F token=admin \
172 -F plugin-ident=manifest \
173 -F plugin-identifier=Implementation-Title=com.example:plugin \
174 "http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
175 {{/code}}
176 )))
177
178 ; update-properties
179 : Updates the properties of the given plugin. You must not specify a JAR file. You should specify at least one of //clear-properties// or //property//. If the given plugin does not exist yet, an error is returned. For example:
180
181 (((
182 {{code language="bash"}}
183 # Delete all existing plugin properties and set the property //foo// to //bar//
184 curl -X POST \
185 -F deploy-action=update-properties \
186 -F token=admin \
187 -F plugin-ident=manifest \
188 -F plugin-identifier=Implementation-Title=com.example:plugin \
189 -F clear-properties=false \
190 -F property=foo=bar \
191 "http://localhost:8080/formcycle/plugin?client-id=154&name=deploy-plugin"
192 {{/code}}
193 )))
194
195 === Response ===
196
197 The plugin deploy servet returns a status code and a JSON object with the details. The status code is 2xx if (and only if) the deploy servlet was executed successfully.
198
199 The JSON object that is returned adheres to the following [[JSON schema>>https://json-schema.org/]]:
200
201 {{code language="json"}}
202 {
203 "$schema": "http://json-schema.org/schema",
204 "description": "Represents the response of the deploy plugin servlet.",
205 "required": [
206 "success",
207 "statusCode",
208 "details",
209 "message",
210 "requestParameters"
211 ],
212 "properties": {
213 "success": {
214 "type": "boolean",
215 "title": "Success status",
216 "description": "true if the deploy plugin servlet was executed successfully, or false otherwise"
217 },
218 "statusCode": {
219 "type": "number",
220 "title": "HTTP status code",
221 "description": "The status code of the HTTP request that contains this response."
222 },
223 "details": {
224 "type": "object",
225 "title": "Result details",
226 "description": "Detailed information about the plugin processed by the deploy plugin servlet.",
227 "oneOf": [
228 {
229 "description": "If the deploy plugin servlet was successful, details about the successfully executed action.",
230 "required": [
231 "id",
232 "uuid",
233 "name",
234 "active",
235 "message"
236 ],
237 "properties": {
238 "id": {
239 "type": "number",
240 "title": "Plugin ID",
241 "description": "The database ID of the processed plugin."
242 },
243 "uuid": {
244 "type": "string",
245 "title": "Plugin UUID",
246 "description": "The UUID of the processed plugin."
247 },
248 "name": {
249 "type": "string",
250 "title": "Plugin name",
251 "description": "The name of the processed plugin, i.e. the file name of the plugin JAR file."
252 },
253 "active": {
254 "type": "boolean",
255 "title": "Plugin activation status",
256 "description": "true if the plugin is now active, false if it is now inactive."
257 },
258 "message": {
259 "type": "string",
260 "title": "Result message",
261 "description": "Human-readable message describing the performed action."
262 }
263 }
264 },
265 {
266 "required": [
267 "exceptionType",
268 "exceptionMessage"
269 ],
270 "description": "If the deploy plugin servlet was unsuccessful, details about the error that occurred.",
271 "properties": {
272 "exceptionType": {
273 "type": "string",
274 "title": "Exception type",
275 "description": "The type of the error that occurred, a fully-classified name of the Java exception class."
276 },
277 "exceptionMessage": {
278 "type": "string",
279 "title": "Exception message",
280 "description": "The human-readable message of the error that occurred."
281 }
282 }
283 }
284 ]
285 },
286 "message": {
287 "type": "string",
288 "title": "Result message",
289 "description": "A human-readable message that describes this result."
290 },
291 "requestParameters": {
292 "type": "object",
293 "title": "Request parameters",
294 "description": "The parameters of the request that triggered this response."
295 }
296 }
297 }
298 {{/code}}
299
300 Example for a response when a plugin was updated successfully:
301
302 {{code language="json"}}
303 {
304 "success": true,
305 "requestParameters": {
306 "plugin-ident": ["manifest"],
307 "name": ["deploy-plugin"],
308 "client-id": ["1"],
309 "deploy-action": ["save"],
310 "plugin-identifier": ["Implementation-Title=com.example:plugin"],
311 "token": ["admin"]
312 },
313 "details": {
314 "name": "my-plugin.jar",
315 "active": true,
316 "id": 203,
317 "message": "Plugin saved successfully.",
318 "uuid": "2fe3e1ba-cb32-434e-9f59-4422f8dabcad"
319 },
320 "message": "Plugin saved successfully.",
321 "statusCode": 200
322 }
323 {{/code}}
324
325 Example for a response when a plugin could not be deleted:
326
327 {{code language="json"}}
328 {
329 "success": false,
330 "requestParameters": {
331 "plugin-ident": ["manifest"],
332 "name": ["deploy-plugin"],
333 "client-id": ["1"],
334 "deploy-action": ["delete"],
335 "plugin-identifier": ["Implementation-Title=com.example:plugin"],
336 "token": ["admin"]
337 },
338 "details": {
339 "exceptionType": "java.lang.IllegalArgumentException",
340 "exceptionMessage": "Deploy action 'delete' requires an existing pluign, but none was found."
341 },
342 "message": "class java.lang.IllegalArgumentException: Deploy action 'delete' requires an existing pluign, but none was found.",
343 "statusCode": 404
344 }
345 {{/code}}
346
347
348 == Create token servlet ==
349
350 This servlet lets you create a hash for a password that you can enter in the plugin property //token//. Make an HTTP GET request to the following URL (change to path to the {{formcycle/}} server and the client ID):
351
352 {{code language="none"}}
353 http://localhost:8080/formcycle/plugin?client-id=1&name=create-token&token=<PASSWORD>&method=<METHOD>
354 {{/code}}
355
356 ; token
357 : The password to hash.
358 ; method
359 : Hash method, default to //sha256//. Supported values are //plain//, //sha256//, //sha384// and //sha512//.
360
361 This returns a JSON object with the same schema as returned by the plugin deploy servlet. For example:
362
363 {{code language="json"}}
364 {
365 "success": true,
366 "requestParameters": {
367 "name": ["create-token"],
368 "client-id": ["1"],
369 "token": ["admin"]
370 },
371 "details": {
372 "method": "sha256",
373 "token": "sha256:S+32GI3fWXwHHulUMtWmjpQ15EqMvgVYguuO9SKxfNw+ckAGQljP6tKlf1EITnU7"
374 },
375 "message": "Hash token created successfully",
376 "statusCode": 200
377 }
378 {{/code}}
379
380 == Maven deploy plugin ==
381
382 To upload a plugin to {{formcycle/}} after building a plugin project via Maven, you can use the maven deploy plugin. It is available from the XIMA artifactory (please note you may need the correct permissions to access this artifact).
383
384 === Confguration ===
385
386 {{code language="xml"}}
387 <plugin>
388 <groupId>de.xima.fc.maven.plugin</groupId>
389 <artifactId>fc-deploy-plugin-maven-plugin</artifactId>
390 <version>1.1.0</version>
391 <configuration>
392 <url>http://localhost:8080/formcycle</url>
393 <pluginName>deploy-plugin</pluginName>
394 <clientId>52</clientId>
395 <token>admin</token>
396 <deployAction>save</deployAction>
397 <pluginIdent>name</manifest>
398 <pluginIdentifier>my-plugin.jar</pluginIdentifier>
399 <jarFile></jarFile>
400 <disallowInstall>false</disallowInstall>
401 <locale>en</locale>
402 <clearProperties>true</clearProperties>
403 <properties>
404 <property1>value1</property1>
405 <property2>value2</property2>
406 <properties>
407 </configuration>
408 </plugin>
409 {{/code}}
410
411 The plugin offers the following configurable settings:
412
413 ; url [Default value: //${fcDeployUrl}//]
414 : URL to the {{formcycle/}} server, including the context path, such as //{{{http://localhost:8080/formcycle}}}//
415 ; pluginName [Default value: //deploy-plugin//]
416 : Name of the deploy plugin, the value for the parameter //name//. Usually you do not need to change this.
417 ; clientId [Default value: //${fcDeployClientId}//]
418 : ID of the client with the plugin to be installed, updated, or deleted. Corresponds to the parameter //client-id// of the plugin deploy servlet, see above.
419 ; clientUuid
420 : Alternative for //clientUUID//. The UUID of the client with the plugin to be installed, updated, or deleted.Corresponds to the parameter //client-uuid// of the plugin deploy servlet, see above.
421 ; token [Standardwert: //${fcDeployToken}//]
422 : Password for the plugin deploy servlet, if one was set in the plugin configuration.
423 ; deployAction [Default value: //save//]
424 : Method to be executed. Allowed values are //save//, //update-properties//, //activate//, //deactivate// and //delete//. Corresponds to the parameter //deploy-action// of the plugin deploy servlet, see above.
425 ; pluginIdent [Default value: //manifest//]
426 : The method for identifying existing plugins. Corresponds to the parameter //plugin-ident// of the plugin deploy servlet, see above.
427 ; pluginIdentifier [Default value: //Implementation-Title=${project.groupId}:${project.artifactId}//]
428 : Identifier of the plugin to be installed, updated, or deleted. Corresponds to the parameter //plugin-identifier// of the plugin deploy servlet, see above.
429 ; jarFile [Default value: Haupt-Build-Artifakt des Maven-Projekts]
430 : Path to the JAR file to be uploaded, relative to the base directory of the maven project.
431 ; disallowInstall [Default value: //false//]
432 : When set to //true// and the plugin does not exists yet, the plugin is not installed and an error is returned. Corresponds to the parameter //disallow-install// of the plugin deploy servlet, see above.
433 ; locale [Standardwert: //en//]
434 : Language for the installations. Corresponds to the parameter //locale// of the plugin deploy servlet, see above.
435 ; clearProperties [Default value: //false//]
436 : Clears all properties of the plugin. Corresponds to the parameter //clear-properties// of the plugin deploy servlet, see above.
437 ; properties
438 : Key value pair with the properties to be set on the plugin. Corresponds to the parameter //property// of the plugin deploy servlet, see above.
439
440 === Recommendations for your plugin project ===
441
442 While the Maven plugin offers a wide variety of options, the default settings are usually sufficient. We recommend the following steps for your plugin:
443
444 Add this code snippet to the profile section of the //pom.xml//:
445
446 {{code language="xml"}}
447 <properties>
448 <fc-deploy-plugin-maven-plugin.version>1.1.0</fc-deploy-plugin-maven-plugin.version>
449 </properties>
450
451 <build>
452 <plugins>
453 <plugin>
454 <groupId>de.xima.fc.maven.plugin</groupId>
455 <artifactId>fc-deploy-plugin-maven-plugin</artifactId>
456 <version>${fc-deploy-plugin-maven-plugin.version}</version>
457 </plugin>
458 </plugins>
459 </build>
460 {{/code}}
461
462 The plugin is identified based on the entry //Implementation-Title// in its //Manifest.MF// file. For this to work, you need to prepare the manifest correctly. You can do so either with the //maven-jar-plugin// or with the //maven-assembly-plugin//, depending on which plugin your project uses.
463
464 {{code language="xml"}}
465 <properties>
466 <xfc.version>6.4.0-SNAPSHOT</xfc.version>
467 <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
468 <maven-assembly-plugin.version>3.2.0</maven-assembly-plugin.version>
469 </properties>
470
471 <build>
472 <plugins>
473
474 <!-- If using the maven-jar-plugin -->
475 <plugin>
476 <groupId>org.apache.maven.plugins</groupId>
477 <artifactId>maven-jar-plugin</artifactId>
478 <version>${maven-jar-plugin.version}</version>
479 <configuration>
480 <outputDirectory>${basedir}</outputDirectory>
481 <finalName>${project.artifactId}</finalName>
482 <archive>
483 <manifest>
484 <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
485 </manifest>
486 <manifestEntries>
487 <formcycle-version-requirement>${xfc.version}</formcycle-version-requirement>
488 <Implementation-Title>${project.groupId}:${project.artifactId}</Implementation-Title>
489 <Implementation-Vendor-Id>${project.groupId}</Implementation-Vendor-Id>
490 <Implementation-Version>${project.version}</Implementation-Version>
491 <Build-Timestamp>${maven.build.timestamp}</Build-Timestamp>
492 </manifestEntries>
493 </archive>
494 </configuration>
495 </plugin>
496
497 <!-- If using the maven-assembly-plugin -->
498 <plugin>
499 <groupId>org.apache.maven.plugins</groupId>
500 <artifactId>maven-assembly-plugin</artifactId>
501 <version>${maven-assembly-plugin.version}</version>
502 <executions>
503 <execution>
504 <id>fat-jar</id>
505 <phase>package</phase>
506 <goals>
507 <goal>single</goal>
508 </goals>
509 <configuration>
510 <outputDirectory>${basedir}</outputDirectory>
511 <finalName>${project.artifactId}</finalName>
512 <descriptorRefs>
513 <descriptorRef>jar-with-dependencies</descriptorRef>
514 </descriptorRefs>
515 <appendAssemblyId>false</appendAssemblyId>
516 <archive>
517 <manifestEntries>
518 <Build-Timestamp>${maven.build.timestamp}</Build-Timestamp>
519 <Implementation-Vendor-Id>${project.groupId}</Implementation-Vendor-Id>
520 <Implementation-Title>${project.groupId}:${project.artifactId}</Implementation-Title>
521 <Implementation-Version>${project.version}</Implementation-Version>
522 <formcycle-version-requirement>${xfc.version}</formcycle-version-requirement>
523 </manifestEntries>
524 </archive>
525 </configuration>
526 </execution>
527 </executions>
528 </plugin>
529
530 </plugins>
531 </build>
532 {{/code}}
533
534 Now you can build the plugin via Maven and upload it to a {{formcycle}} server. The URL, the client ID and the token (password) can be passed to Maven via command line parameters:
535
536 {{code language="bash"}}
537 mvn package fc-deploy:deploy -DfcDeployUrl="http://localhost:8080/xima-formcycle" -DfcDeployClientId="1" -DfcDeployToken="admin"
538 {{/code}}
539
540 If you do not pass these parameters, the deploy plugin is not executed and the plugin is not uploaded.
541
542 On a side note: IDE such as Eclipse and IntelliJ let you create a build configuration for your plugin project, where you can enter the parameters //fcDeployUrl//, //fcDeployClientId// and //fcDeployToken//. This way you can upload the plugin simply by running the build configuration.
543
544 == Changelog
545
546 This is a list of available version of this plugin and which changes took place in which version.
547
548 === 7.0.1 ===
549
550 * Minor improvement when handling errors
551
552 === 7.0.0 ===
553
554 * Modifications to make the plugin work with {{formcycle/}} 7.0.
555
556 === 1.1.0
557
558 * Modifications to make the plugin work with {{formcycle/}} 6.4.
559
560 === 1.0.1
561
562 * Improved error handling when an uploaded plugin is installed
563
564 === 1.0.0
565
566 * Initial release