baf61d50a3057c61f8e81f89ef8c185069343fa6
[policy/parent.git] / docs / clamp / acm / acm-participant-guide.rst
1 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2 .. http://creativecommons.org/licenses/by/4.0
3 .. Copyright (c) Nordix Foundation.  All rights reserved.
4
5 .. _acm-participant-guide-label:
6
7 Participant developer guide
8 ###########################
9
10 .. contents::
11     :depth: 4
12
13 The ACM runtime delegates the user requests to the participants for performing the actual operations.
14 Hence the participant module in ACM is implemented adhering to a list of ACM protocols along with their own functional logic.
15 It works in a contract with the Participant Intermediary module for communicating with ACM-R.
16 This guide explains the design considerations for a new participant implementation in ACM.
17
18 Please refer the following section for a detailed understanding of Inbound and outbound messages a participant interacts with.
19
20 .. toctree::
21    :maxdepth: 2
22
23    design-impl/participants/participants
24
25 Design considerations for a participant
26 ---------------------------------------
27
28 In ONAP, the ACM-runtime and participant modules are implemented in Java spring boot. The participant Intermediary module
29 which is added as a maven dependency to the participants has the default implementations available for listening the kafka
30 events coming in from the ACM-runtime, process them and delegate them to the appropriate handler class. Similarly the
31 Intermediary module also has the publisher class implementations for publishing events back from the participants to the ACM-runtime.
32
33 Hence the new participants has to have this Participant Intermediary module as a dependency and should:
34
35 * Configure SpringBoot to scan the components located into the package "org.onap.policy.clamp.acm.participant.intermediary".
36 * Implement the following interfaces from the Participant Intermediary.
37 * Provide the following mandatory properties in order to make the participant work in synchronisation with ACM-runtime.
38
39 The participant application should be provided with the following Intermediary parameter values in the application properties
40 and the same is configured for the 'ParticipantIntermediaryParameters' object in the code.
41
42 1. participantId - A unique participant UUID that is used by the runtime to identify the participant.
43 2. ReportingTimeIntervalMs - Time inertval the participant should report the status/heartbeat to the runtime.
44 3. clampAutomationCompositionTopics - This property takes in the kafka topic names and servers for the intermediary module to use.
45    These values should be provided for both source and sink configs. The following example shows the topic parameters set for using DMaap.
46
47 .. code-block:: bash
48
49     clampAutomationCompositionTopics:
50           topicSources:
51             -
52               topic: POLICY-ACRUNTIME-PARTICIPANT
53               servers:
54                 - ${topicServer:localhost}
55               topicCommInfrastructure: dmaap
56               fetchTimeout: 15000
57           topicSinks:
58             -
59               topic: POLICY-ACRUNTIME-PARTICIPANT
60               servers:
61                 - ${topicServer:localhost}
62               topicCommInfrastructure: dmaap
63
64 4. participantSupportedElementTypes - This property takes a list of typeName and typeVersion fields to define the types of AC elements the participant deals with.
65    These are user defined name and version and the same should be defined for the AC elements that are included in the TOSCA based AC definitions.
66
67 .. code-block:: bash
68
69     participantSupportedElementTypes:
70       -
71         typeName: org.onap.policy.clamp.acm.PolicyAutomationCompositionElement
72         typeVersion: 1.0.0
73
74 Interfaces to Implement
75 -----------------------
76 AutomationCompositionElementListener:
77   Every participant should implement a handler class that implements the AutomationCompositionElementListener interface
78   from the Participant Intermediary. The intermediary listener class listens for the incoming events from the ACM-runtime
79   and invoke the handler class implementations for various operations. This class implements the methods for deploying,
80   undeploying, locking, unlocking , deleting, updating, migrating, priming, depriming requests that are coming from the ACM-runtime.
81   The methods are as follows.
82
83 .. code-block:: java
84
85   1. void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
86   2. void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
87   3. void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
88   4. void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
89   5. void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
90   6. void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, InstanceElementDto instanceElementUpdated) throws PfModelException;
91   7. void prime(CompositionDto composition) throws PfModelException;
92   8. void deprime(CompositionDto composition) throws PfModelException;
93   9. void handleRestartComposition(CompositionDto composition, AcTypeState state) throws PfModelException;
94   10. void handleRestartInstance(CompositionElementDto compositionElement, InstanceElementDto instanceElement, DeployState deployState, LockState lockState) throws PfModelException;
95   11. void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException;
96
97 These method from the interface are implemented independently as per the user requirement. These methods after handling the
98 appropriate requests should also invoke the intermediary's publisher apis to notify the ACM-runtime with the acknowledgement events.
99
100 ParticipantParameters:
101   Every participant should implement a properties class that contains the values of all Intermediary parameter properties.
102   This class implements the method getIntermediaryParameters that returns 'ParticipantIntermediaryParameters' object. The method is as follows.
103
104 .. code-block:: java
105
106   ParticipantIntermediaryParameters getIntermediaryParameters()
107
108 Abstract class AcElementListenerV1
109 ----------------------------------
110 This abstract class is introduced to help to maintain the java backward compatibility with AutomationCompositionElementListener implemented in 7.1.0 version.
111 So developers can decide to align to new functionality later. Any new functionality in the future will be wrapped by this class.
112
113 The Abstract class AcElementListenerV1 supports the follow methods.
114
115 .. code-block:: java
116
117   1. void undeploy(UUID instanceId, UUID elementId) throws PfModelException;
118   2. void deploy(UUID instanceId, AcElementDeploy element, Map<String, Object> inProperties) throws PfModelException;
119   3. void lock(UUID instanceId, UUID elementId) throws PfModelException;
120   4. void unlock(UUID instanceId, UUID elementId) throws PfModelException;
121   5. void delete(UUID instanceId, UUID elementId) throws PfModelException;
122   6. void update(UUID instanceId, AcElementDeploy element, Map<String, Object> inProperties) throws PfModelException;
123   7. void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) throws PfModelException;
124   8. void deprime(UUID compositionId) throws PfModelException;
125   9. void handleRestartComposition(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList, AcTypeState state) throws PfModelException;
126   10. void handleRestartInstance(UUID instanceId, AcElementDeploy element, Map<String, Object> properties, DeployState deployState, LockState lockState) throws PfModelException;
127   11. void migrate(UUID instanceId, AcElementDeploy element, UUID compositionTargetId, Map<String, Object> properties) throws PfModelException;
128
129 **Note**: this class needs intermediaryApi and it should be passed by constructor. It is declared as protected and can be used.
130 Default implementation are supported for the methods: lock, unlock, update, migrate, delete, prime, deprime, handleRestartComposition and handleRestartInstance.
131
132 Un example of AutomationCompositionElementHandler implemented in 7.1.0 version and how to use AcElementListenerV1 abstract class:
133
134 .. code-block:: java
135
136   @Component
137   @RequiredArgsConstructor
138   public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
139
140     private final ParticipantIntermediaryApi intermediaryApi;
141     private final otherService otherService;
142     ..............................
143   }
144
145   @Component
146   public class AutomationCompositionElementHandler extends AcElementListenerV1 {
147
148     private final OtherService otherService;
149
150     public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi, OtherService otherService) {
151         super(intermediaryApi);
152         this.otherService = otherService;
153     }
154     ..............................
155   }
156
157
158
159 A second example:
160
161 .. code-block:: java
162
163   @Component
164   public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
165
166     @Autowired
167     private ParticipantIntermediaryApi intermediaryApi;
168
169     @Autowired
170     private otherService otherService;
171     ..............................
172   }
173
174   @Component
175   public class AutomationCompositionElementHandler extends AcElementListenerV1 {
176
177     @Autowired
178     private otherService otherService;
179
180     public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi) {
181         super(intermediaryApi);
182     }
183     ..............................
184   }
185
186 Abstract class AcElementListenerV2
187 ----------------------------------
188 This abstract class is introduced to help to maintain the java backward compatibility with AutomationCompositionElementListener from new releases.
189 Any new functionality in the future will be wrapped by this class.
190
191 **Note**: this class needs intermediaryApi and it should be passed by constructor. It is declared as protected and can be used.
192 Default implementation are supported for the methods: lock, unlock, update, migrate, delete, prime, deprime, handleRestartComposition and handleRestartInstance.
193
194
195 APIs to invoke
196 --------------
197 ParticipantIntermediaryApi:
198   The participant intermediary api has the following methods that can be invoked from the participant for the following purposes.
199
200   #. The requested operations are completed in the handler class and the ACM-runtime needs to be notified.
201   #. Collect all instances data.
202   #. Send out Properties to ACM-runtime.
203
204   The methods are as follows:
205
206 This following methods could be invoked to fetch data during each operation in the participant.
207
208 .. code-block:: java
209
210   1.  Map<UUID, AutomationComposition> getAutomationCompositions();
211   2.  AutomationComposition getAutomationComposition(UUID instanceId);
212   3.  AutomationCompositionElement getAutomationCompositionElement(UUID instanceId, UUID elementId);
213   4.  Map<UUID, Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition>> getAcElementsDefinitions();
214   5.  Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> getAcElementsDefinitions(UUID compositionId);
215   6.  AutomationCompositionElementDefinition getAcElementDefinition(UUID compositionId, ToscaConceptIdentifier elementId);
216
217 This following methods are invoked to update the outProperties during each operation in the participant.
218
219 .. code-block:: java
220
221   1.  void sendAcDefinitionInfo(UUID compositionId, ToscaConceptIdentifier elementId, Map<String, Object> outProperties);
222   2.  void sendAcElementInfo(UUID instanceId, UUID elementId, String useState, String operationalState, Map<String, Object> outProperties);
223
224 This following methods are invoked to update the AC element state or AC element definition state after each operation is completed in the participant.
225
226 .. code-block:: java
227
228   1.  void updateAutomationCompositionElementState(UUID instanceId, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message);
229   2.  void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult, String message);
230
231 In/Out composition Properties
232 -----------------------------
233 The 'Common Properties' could be created or updated by ACM-runtime.
234 Participants will receive that Properties during priming and deprime events by CompositionDto class.
235
236 .. code-block:: java
237
238   @Override
239   public void prime(CompositionDto composition) throws PfModelException {
240       for (var entry : composition.inPropertiesMap().entrySet()) {
241           var elementDefinitionId = entry.getKey();
242           var inProperties = entry.getValue();
243           .......
244       }
245       .......
246   }
247
248 Participants will receive the Properties related to the element definition by CompositionElementDto class.
249
250 .. code-block:: java
251
252   @Override
253   public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {
254       var inCompositionProperties = compositionElement.inProperties();
255       .......
256   }
257
258 The 'Out Properties' could be created or updated by participants. ACM-runtime will receive that Properties during ParticipantStatus event.
259 The participant can trigger this event using the method sendAcDefinitionInfo.
260
261 Participants will receive that outProperties during priming and deprime events by CompositionDto class.
262
263 .. code-block:: java
264
265   @Override
266   public void deprime(CompositionDto composition) throws PfModelException {
267       for (var entry : composition.outPropertiesMap().entrySet()) {
268           var elementDefinitionId = entry.getKey();
269           var outProperties = entry.getValue();
270           .......
271       }
272       .......
273   }
274
275 Participants will receive the outProperties related to the element definition by CompositionElementDto class.
276
277 .. code-block:: java
278
279   @Override
280   public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {
281       var outCompositionProperties = compositionElement.outProperties();
282       .......
283   }
284
285 Is allowed to the participant to read all In/Out Properties of all compositions handled by the participant using the method getAcElementsDefinitions.
286 The following code is an example how to update the property 'myProperty' and send to ACM-runtime:
287
288 .. code-block:: java
289
290   var acElement = intermediaryApi.getAcElementDefinition(compositionId, elementDefinitionId);
291   var outProperties = acElement.getOutProperties();
292   outProperties.put("myProperty", myProperty);
293   intermediaryApi.sendAcDefinitionInfo(compositionId, elementDefinitionId, outProperties);
294
295 In/Out instance Properties
296 --------------------------
297   The 'In/Out Properties' are stored into the instance elements, so each element has its own In/Out Properties.
298
299   The 'In Properties' could be created or updated by ACM-runtime. Participants will receive that Properties during deploy and update events.
300
301   The 'Out Properties' could be created or updated by participants. ACM-runtime will receive that Properties during ParticipantStatus event.
302   The participant can trigger this event using the method sendAcElementInfo. The 'useState' and 'operationalState' can be used as well.
303   The 'Out Properties' could be **cleaned**:
304
305   * by the participant using the method sendAcElementInfo
306   * by intermediary automatically during deleting of the instance
307   * by an update when the instance is in UNDEPLOYED state (changing the elementId)
308
309   The 'Out Properties' will be **not cleaned** by intermediary:
310
311   * during DEPLOIYNG (Out Properties will be take from last changes matching by elementId)
312   * during UNDEPLOING
313   * during LOCKING/UNLOCKING
314   * during UPDATING/MIGRATING
315
316 Participants will receive the in/out instance Properties related to the element by InstanceElementDto class.
317
318 .. code-block:: java
319
320   @Override
321   public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {
322       var inProperties = instanceElement.inProperties();
323       var outProperties = instanceElement.outProperties();
324       .......
325   }
326
327 Is allowed to the participant to read all In/Out Properties and state of all instances handled by the participant using the method getAutomationCompositions.
328 The following code is an example how to update the property 'myProperty' and send to ACM-runtime:
329
330 .. code-block:: java
331
332   var acElement = intermediaryApi.getAutomationCompositionElement(instanceId, elementId);
333   var outProperties = acElement.getOutProperties();
334   outProperties.put("myProperty", myProperty);
335   intermediaryApi.sendAcElementInfo(instanceId, elementId, acElement.getUseState(), acElement.getOperationalState(), outProperties);
336
337 **Note**: In update and migrate Participants will receive the instance Properties before the merge (instanceElement) and the instance Properties merged (instanceElementUpdated / instanceElementMigrate).
338
339 Restart scenario
340 ----------------
341   Restart methods handle the scenario when participant shut down and restart.
342   During RESTARTING, compositions and instances will be stored in participant memory with In/Out Properties, 'useState' and 'operationalState'.
343   The method handleRestartComposition will be called for each composition and will be present the 'state' at the time the participant shut down.
344   The method handleRestartInstance will be called for each instance element and will be present the 'deployState' and the 'lockState' at the time the participant shut down.
345
346 In ONAP, the following participants are already implemented in java spring boot for various requirements. The maven modules
347 can be referred here:
348
349   * `HTTP participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-http>`_.
350   * `Kubernetes participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-kubernetes>`_.
351   * `Policy participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-policy>`_.
352   * `A1PMS participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-a1pms>`_.
353   * `Kserve participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-kserve>`_.
354
355 Example of Implementation
356 -------------------------
357
358 This following code is an example of My First Participant:
359   * Application
360   * Parameters
361   * Handler
362
363 The Application class is configured to add the "org.onap.policy.clamp.acm.participant.intermediary" package in SpringBoot component scanning.
364
365 .. code-block:: java
366
367   @SpringBootApplication
368   @ComponentScan({
369     "org.onap.policy.clamp.acm.participant.myfirstparticipant",
370     "org.onap.policy.clamp.acm.participant.intermediary"
371   })
372   @ConfigurationPropertiesScan("org.onap.policy.clamp.acm.participant.myfirstparticipant.parameters")
373   public class MyFirstParticipantApplication {
374
375     public static void main(String[] args) {
376       SpringApplication.run(Application.class, args);
377     }
378   }
379
380 The Participant Parameters class implements the mandatory interface ParticipantParameters.
381 It could contains additional parameters.
382
383 .. code-block:: java
384
385   @Validated
386   @Getter
387   @Setter
388   @ConfigurationProperties(prefix = "participant")
389   public class ParticipantSimParameters implements ParticipantParameters {
390
391     @NotBlank
392     private String myparameter;
393
394     @NotNull
395     @Valid
396     private ParticipantIntermediaryParameters intermediaryParameters;
397   }
398
399 The following example shows the topic parameters and the additional 'myparameter'.
400
401 .. code-block:: bash
402
403   participant:
404     myparameter: my parameter
405     intermediaryParameters:
406       reportingTimeIntervalMs: 120000
407       description: Participant Description
408       participantId: 101c62b3-8918-41b9-a747-d21eb79c6c90
409       clampAutomationCompositionTopics:
410         topicSources:
411           - topic: POLICY-ACRUNTIME-PARTICIPANT
412             servers:
413               - ${topicServer:localhost}
414             topicCommInfrastructure: dmaap
415             fetchTimeout: 15000
416         topicSinks:
417           - topic: POLICY-ACRUNTIME-PARTICIPANT
418             servers:
419               - ${topicServer:localhost}
420             topicCommInfrastructure: dmaap
421       participantSupportedElementTypes:
422         -
423           typeName: org.onap.policy.clamp.acm.MyFirstAutomationCompositionElement
424           typeVersion: 1.0.0
425
426
427 The following example shows the Handler implementation and how could be the implemented the mandatory notifications.
428
429 .. code-block:: java
430
431   @Component
432   public class AutomationCompositionElementHandler extends AcElementListenerV2 {
433
434     @Override
435     public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
436             throws PfModelException {
437
438         // TODO deploy process
439
440         if (isDeploySuccess()) {
441             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
442                 instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR,
443                 "Deployed");
444         } else {
445             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
446                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
447                 "Deploy failed!");
448         }
449     }
450
451     @Override
452     public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
453             throws PfModelException {
454
455         // TODO undeploy process
456
457         if (isUndeploySuccess()) {
458             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
459                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR,
460                     "Undeployed");
461         } else {
462             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
463                 instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED,
464                     "Undeploy failed!");
465         }
466     }
467
468     @Override
469     public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
470             throws PfModelException {
471
472         // TODO lock process
473
474         if (isLockSuccess()) {
475             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
476                 instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
477         } else {
478             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
479                 instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
480         }
481     }
482
483     @Override
484     public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
485             throws PfModelException {
486
487         // TODO unlock process
488
489         if (isUnlockSuccess()) {
490             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
491                 instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
492         } else {
493             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
494                 instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
495         }
496     }
497
498     @Override
499     public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
500             throws PfModelException {
501
502         // TODO delete process
503
504         if (isDeleteSuccess()) {
505             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
506                 instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
507         } else {
508             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
509                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
510                 "Delete failed!");
511         }
512     }
513
514     @Override
515     public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
516                        InstanceElementDto instanceElementUpdated) throws PfModelException {
517
518         // TODO update process
519
520         if (isUpdateSuccess()) {
521             intermediaryApi.updateAutomationCompositionElementState(
522                 instanceElement.instanceId(), instanceElement.elementId(),
523                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
524         } else {
525             intermediaryApi.updateAutomationCompositionElementState(
526                 instanceElement.instanceId(), instanceElement.elementId(),
527                 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
528         }
529     }
530
531     @Override
532     public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget,
533                         InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate)
534         throws PfModelException
535
536         // TODO migrate process
537
538         if (isMigrateSuccess()) {
539             intermediaryApi.updateAutomationCompositionElementState(
540                 instanceElement.instanceId(), instanceElement.elementId(),
541                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
542         } else {
543             intermediaryApi.updateAutomationCompositionElementState(
544                 instanceElement.instanceId(), instanceElement.elementId(),
545                 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!");
546         }
547     }
548
549     @Override
550     public void prime(CompositionDto composition) throws PfModelException {
551
552         // TODO prime process
553
554         if (isPrimeSuccess()) {
555             intermediaryApi.updateCompositionState(composition.compositionId(),
556                 AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed");
557         } else {
558             intermediaryApi.updateCompositionState(composition.compositionId(),
559                 AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!");
560         }
561     }
562
563     @Override
564     public void deprime(CompositionDto composition) throws PfModelException {
565
566         // TODO deprime process
567
568         if (isDeprimeSuccess()) {
569             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
570                 StateChangeResult.NO_ERROR, "Deprimed");
571         } else {
572             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
573                 StateChangeResult.FAILED, "Deprime failed!");
574         }
575     }
576
577
578     @Override
579     public void handleRestartComposition(CompositionDto composition, AcTypeState state) throws PfModelException {
580
581          // TODO restart process
582
583         switch (state) {
584             case PRIMING -> prime(composition);
585             case DEPRIMING -> deprime(composition);
586             default -> intermediaryApi
587                 .updateCompositionState(composition.compositionId(), state, StateChangeResult.NO_ERROR, "Restarted");
588         }
589     }
590
591     @Override
592     public void handleRestartInstance(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
593         DeployState deployState, LockState lockState) throws PfModelException {
594
595          // TODO restart process
596
597         if (DeployState.DEPLOYING.equals(deployState)) {
598             deploy(compositionElement, instanceElement);
599             return;
600         }
601         if (DeployState.UNDEPLOYING.equals(deployState)) {
602             undeploy(compositionElement, instanceElement);
603             return;
604         }
605         if (DeployState.UPDATING.equals(deployState)) {
606             update(compositionElement, instanceElement, instanceElement);
607             return;
608         }
609         if (DeployState.DELETING.equals(deployState)) {
610             delete(compositionElement, instanceElement);
611             return;
612         }
613         if (LockState.LOCKING.equals(lockState)) {
614             lock(compositionElement, instanceElement);
615             return;
616         }
617         if (LockState.UNLOCKING.equals(lockState)) {
618             unlock(compositionElement, instanceElement);
619             return;
620         }
621         intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
622             instanceElement.elementId(), deployState, lockState, StateChangeResult.NO_ERROR, "Restarted");
623     }
624
625
626 AC Element states in failure scenarios
627 --------------------------------------
628
629 During the execution of any state change order, there is always a possibility of failures or exceptions that can occur in the participant.
630 This can be tackled by the followed approaches.
631
632 The participant implementation can handle the exception and revert back the appropriate AC element state, by invoking the
633 'updateAutomationCompositionElementState' api from the participant intermediary.
634
635 Alternatively, the participant can simply throw a PfModelException from its implementation which will be handled by the participant intermediary.
636 The intermediary handles this exception and rolls back the AC element to its previous state with the appropriate stateChange Result.
637 Please refer the following table for the state change reversion that happens in the participant intermediary for the AC elements.
638
639 ================== ==================
640 **Error Scenario** **State Reverted**
641 ================== ==================
642 Prime fails        Commissoned
643
644 Deprime fails      Primed
645
646 Deploy fails       Undeployed
647
648 Undeploy fails     Deployed
649
650 Update fails       Deployed
651
652 Delete fails       Undeployed
653
654 Lock fails         Unlocked
655
656 Unlock fails       Locked
657
658 Migrate fails      Deployed
659 ================== ==================
660
661 Considering the above mentioned behavior of the participant Intermediary, it is the responsibility of the developer to tackle the
662 error scenarios in the participant with the suitable approach.
663
664 Tips:
665 If the participant tries to undeploy an element which doesn’t exist in the system any more (due to various other external factors),
666 it could update the element state to ‘undeployed’ using the Intermediary api.