Skip to content
This repository has been archived by the owner on Jun 26, 2021. It is now read-only.

The Workflow Format

Stanley Hillner edited this page Apr 26, 2019 · 9 revisions

The business logic of a plugin depending on the AbstractCDIMojo is implemented in several processing steps. Each step should only implement a small amount of work that is logically independent from other features. Now, implementing the processing logic as loosely coupled units can surely give a boost to maintainability, testability or reusability but doesn't make up a fully functional Mojo yet. And this is the point where workflow orchestration comes to play.

What Are Workflows

Workflows are ther to orchestrate the execution of your processing steps. This means that a workflow determines a fixed order in which a number of processing steps are executed. These can be steps contained in your plugin or steps contained in JARs that have been added as plugin-dependencies.

Processing steps can be executed sequentially or in parallel. One workflow can execute one and the same step multiple times and one step can be used in multiple workflows. Each Mojo of a plugin must provide a default workflow for its execution.

Default Workflows And Workflow Overriding

Default workflows are required for each goal of your plugin. Without such a default workflow the goal would provide no funtionality. If no default workflow is present the build will fail.

These are the requirements for the default workflows:

  • The workflow file must be named as the name of the goal it is intended for
  • The storage location for default workflows is the folder plugin.jar/META-INF/workflows

If your plugin is f.i. named test-maven-plugin and your goal is named unit-test then the default workflow must be specified in test-maven-plugin.jar/META-INF/workflows/unit-test.

The user is also free to override this default workflow at runtime in order to skipt processing steps or extend the workflow with further functionality. An alternative workflow can either be configured in the POM configuration or using a system property: -Dworkflow=<path_to_your_workflow> These configuration options are implicit for all plugins.

<plugin>
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <executions>
      <execution>
        ...
        <configuration>
          <workflowDescriptor>path_to_your_workflow</workflowDescriptor>
        </configuration>
      </execution>
  </executions>
</plugin>

You can check if the goal uses the correct workflow (your customized one instead of the default one) by either observing the log output during the build run. If your workflow has been loaded correctly the following line will occur there:

[INFO] 15:17:14,525 Workflow of goal 'test:unit-test' will be overriden by file '<path_to_your_workflow>'.

Another option the verify that the goal takes your workflow is to print the currently used workflow only instead of running the processing logic:

mvn test:unit-test -Dworkflow=<path_to_your_workflow> -DprintWorkflow

Workflow Format

Workflow files are text files that simply list all processing steps to be executed on separate lines. But there are also some more concepts:

  • If a line starts with a # then the line will be treated as a comment.
  • Steps listed on separate lines are executed in the respective order sequentially.
  • Embed steps in parallel {} to execute these steps in parallel rather than sequentially.
  • If steps shall be executed multiple times then those steps must be qualified in the workflow.
    • embed the qualifier in [] and append it to the step id
  • Since 3.2.0 it is now possible to declare default execution data and default rollback data for processing hooks.
    • This can be done directly in the workflow descriptor.
    • Default data declarations can be overridden by setting the appropriate system properties when calling Maven.
    • Open a block {} for a processing step and declare data and rollbackData on separate lines.
  • Since 3.2.0 it is now also possible to declare a try-finally block surrounding the actual workflow.
    • This concept divides the workflow into two parts, the regular workflow and the finally workflow.
    • The finally workflow is guaranteed to be executed even if the regular workflow fails and is rolled back.
    • Rollback is also supported for the finally workflow.
    • Try block opening must be the first statement of the workflow descriptor (only comment lines may occur beforehand).
    • The try block must be closed with a finally block opening.
    • The finally block must also be closed and is required to be the last element, except comment lines.
# This is a comment
# This example shows sequential ordering of step executions
pre-test
test
post-test
# This example shows sequential and parallel step ordering
pre-test
parallel {
  checkExecutable
  checkEnvironment
}
test
post-test
# This example shows multiple step executions using qualifiers
pre-test
checkEnvironment[1]
test
checkEnvironment[2]
post-test
# This example shows the declaration of default execution data
pre-test
test
exec {
  data=echo test
  rollbackData=echo rollback
}
post-test
# This a more complex example for default execution data declaration
# It declares a first step that executes some commands that have to be specified during the Maven invocation.
# After that two REST calls are made in parallel in order to disable two Jenkins jobs before a second exec prints a message
exec[1]
parallel {
  http[1] {
    data = url=>http://localhost:8081/jenkins/a/disable, method=>POST
    rollbackData=url=>http://localhost:8081/jenkins/a/enable, method=>POST
  }
  http[2] {
    data = url=>http://localhost:8081/jenkins/b/disable, method=>POST
    rollbackData=url=>http://localhost:8081/jenkins/b/enable, method=>POST
  }
}
exec[2] {
  data=echo "disabled jobs"
  rollbackData=echo "anything went wrong!"
}
# This is an example usage of the try-finally concept
try {
  step1[1]
  parallel {
    step2 {
      data=...
      rollbackData=...
    }
    step1[2]
  }
} finally {
  step3
  step1[3] {
    data=...
    rollbackData=...
  }
}

Workflow Information

When overriding the default workflow the user needs some information about what is included in the default workflow and what is available for custom workflow orchestration. For this reason there are two system properties to get exactly this information. Both features can be invoked by calling the respective plugin goal with the property appended.

Printing the default workflow

Assuming your plugin has the prefix test and the goal of interest is named unit-test then you should call mvn test:unit-test -DprintWorkflow. This will result in an output similar to this one:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] test-1
[INFO] module-1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building test-1 26-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- test-maven-plugin:1.0.0:unit-test (default-cli) @ test-1 ---
[INFO] 15:23:44,800  Default workflow for 'test:unit-test':
[INFO] 15:23:44,802  Constructing workflow for processing
[INFO] 15:23:44,802  Goal 'test:unit-test' will use default workflow packaged with the plugin.
================================= unit-test ===================================
# default workflow for our test example
pre-test
test
post-test
================================= unit-test ===================================
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] test-1 ............................................. SUCCESS [  0.711 s]
[INFO] module-1 ........................................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.194 s
[INFO] Finished at: 2016-07-21T15:23:44+02:00
[INFO] Final Memory: 12M/245M
[INFO] ------------------------------------------------------------------------

Printing Available Processing Steps

For printing all available processing steps that can be orchestrated to a workflow you should use mvn test:unit-test -DprintSteps. The output will print a table of all processing steps that have been found on classpath which includes also the steps that have been added as plugin-dependencies. The produced output will look like the following:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] test-1
[INFO] module-1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building test-1 26-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- test-maven-plugin:1.0.0:unit-test (default-cli) @ test-1 ---
[INFO] WELD-000900: 2.3.3 (Final)
[INFO] WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
[INFO] WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
[INFO] 15:39:02,881  The following processing steps are available on classpath and can be configured as part of a custom workflow.
┌────────────────────┬──────────────────────────────────────────────────┬──────────┐
│         ID         │                   DESCRIPTION                    │ REQUIRES │
│                    │                                                  │  ONLINE  │
╞════════════════════╪══════════════════════════════════════════════════╪══════════╡
│ post-test          │ Evaluates the results of the test execution.     │  false   │
├────────────────────┼──────────────────────────────────────────────────┼──────────┤
│ pre-test           │ Prepares test for execution.                     │  false   │
├────────────────────┼──────────────────────────────────────────────────┼──────────┤
│ test               │ Executes unit tests.                             │  false   │
└────────────────────┴──────────────────────────────────────────────────┴──────────┘

[INFO] WELD-ENV-002001: Weld SE container STATIC_INSTANCE shut down
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] test-1 ............................................. SUCCESS [  1.752 s]
[INFO] module-1 ........................................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.205 s
[INFO] Finished at: 2016-07-21T15:39:02+02:00
[INFO] Final Memory: 18M/256M
[INFO] ------------------------------------------------------------------------