Tuesday, August 17, 2021

LRA annotation checker Maven plugin

With the release of the LRA (Long Running Actions) specification in version 1.0 Narayana team works on integrating the Narayana implementation to various application runtimes. Currently it's Quarkus and WildFly. (Camel is a third platform integrating the Narayana implementation but it does in a way not depending on LRA annotations defined in the specification.).

NOTE: If you want to get introduction what is LRA and what is good for you can read some of the already published articles (1, 2).

At this time when the LRA  can be easily grab and used within the application runtimes it may come some difficulty on precise use of the LRA annotations.

The specification defines different "requirements" the LRA application has to follow to work correctly. Some are basic as "the LRA annotated class must contain at least one of the methods annotated with @Compensate or @AfterLRA" or that the LRA annotated JAX-RS endpoints has predefined HTTP methods to be declared with. For example the @Complete/@Compensate requires the @PUT method while the @Forgot requires the @DELETE and @Status requires the @GET.

When the specific LRA contract rule is violated the developer will find them at the deployment time with the RuntimeException being thrown. But time of the deployment could be a bit late to find just a forgotten annotation required by the LRA specification. With that idea in mind Narayana offers a Maven plugin project Narayana LRA annotation checker.

The developer working with the LRA introduces the dependency to the LRA annotation with artifact org.eclipse.microprofile.lra:microprofile-lra-api:1.0. He codes the application and then he can introduce the Maven plugin of the LRA checker to be run during Maven phase process-classes. The developer needs to point to the plugin goal check to get the verification being run.

The snippets that can be placed to the project pom.xml is following. The plugin Maven artifact coordinates is io.narayana:maven-plugin-lra-annotations_1.0:1.0.0.Beta1

...
<build>
  <plugins>
    <plugin>
      <groupId>io.narayana</groupId>
      <artifactId>maven-plugin-lra-annotations_1.0</artifactId>
      <version>1.0.0.Beta1</version>
      <executions>
        <execution>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
...

When plugin is loaded it searches for classes available at path ${project.build.directory}/classes (i.e., target/classes) and tries to find if the application preserve the rules defined by the LRA specification. When not then the Maven build fails reporting what error happens.
Such an error is in format of [error id]:[description]. Example of such error is

[ERROR] Failed to execute goal io.narayana:maven-plugin-lra-annotations_1.0:1.0.0.Beta1:check (default) on project lra-annotation-checker-maven-plugin-test: LRA annotation errors:
[ERROR] [[4]]->
  1: The class annotated with org.eclipse.microprofile.lra.annotation.ws.rs.LRA missing at least one of the annotations Compensate or AfterLRA Class: io.narayana.LRAParticipantResource;
  2: Multiple annotations of the same type are used. Only one per the class is expected. Multiple annotations 'org.eclipse.microprofile.lra.annotation.Status' in the class 'class io.narayana.LRAParticipantResource' on methods [status, status2].;
  4: Wrong method signature for non JAX-RS resource method. Signature for annotation 'org.eclipse.microprofile.lra.annotation.Forget' in the class 'io.narayana.LRAParticipantResource' on method 'forget'. It should be 'public void/CompletionStage/ParticipantStatus forget(java.net.URI lraId, java.net.URI parentId)';
  5: Wrong complementary annotation of JAX-RS resource method. Method 'complete' of class 'class io.narayana.LRAParticipantResource' annotated with 'org.eclipse.microprofile.lra.annotation.Complete' misses complementary annotation javax.ws.rs.PUT.

The plugin can be configured with two parameters (placed under <configuration> under the <plugin> element).

Attribute Description Default
paths Paths searched for classes to be checked. Point to a directory or jar file. Multiple paths are delimited with a comma. ${project.build.directory}/classes
failWhenPathNotExist When some path defined within argument paths does not exist then Maven build may fail or resume with information that the path is not available. true

All the points described in this article can be seen and tested in an example at github.com/jbosstm/artifacts#jbossts.blogspot/17-08-2021-lra-annotation-checker. The plugin configuration can be seen in the pom.xml of the same project.

Any comments, ideas for enhancement and bug reports are welcomed. The project LRA annotation checker Maven plugin is placed in the jbosstm incubator repository. The issues can be submitted via JBTM issue tracker at https://issues.jboss.org/browse/JBTM.

Hopefully this small plugin provides a better experience for any developer working with the LRA and LRA Narayana implementation in particular.