Which lifecycle for a Java annotation that generates documentation? - java

I would like to be able to document the dependencies of my services directly in my code, using Java annotations. Those annotations could bear the information about the target system, whether the connection is incoming/outgoing/2-ways, and the type of connection (REST, RabbitMQ...).
It could look like this:
#Dependency(target = "Twitter API", type = "Outgoing", medium = "REST")
The idea would be to generate a DOT file from all the annotations inside the project.
I have a fair idea on how to create my own annotation, with the required attributes. However, i am not sure at which part of the lifecycle of the compilation/processing i should handle those annotations.
I understand that the annotation processors generate source files, but in my case the generated files are not at all required by the compiler nor the application itself.
Ideally i would like to be able to trigger the annotation processing, and DOT file generation, by a dedicated Maven or Gradle task.
Is it something that is easily doable when writing my own annotations?

If you want to create documentation via maven than you need add the bellow two dependencies as plugins and then execute site maven goal.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
If you just want to document REST endpoints than you can use swagger.
If your project uses spring than the integration of swagger is pretty easy. You can use this tutorial.
If you want to save in a file the dependency graph of your project you can simply execute the following maven command.
mvn dependency:tree -Doutput=/path/to/file

Annotations are processed by the Java compiler directly.
For Maven, one can use the maven-compiler-plugin. It is also possible to perform the compilation in 2 steps, as explained here.
For Gradle, one can add the processors in the dependencies block under the annotationProcessor configuration, as explained here.
Annotation retention can be specified as SOURCE, so they won't be kept after compilation.

Related

How to ignore a dependency in dependency-lock-maven-plugin

In my maven project I want to implement dependency-locking.
One approach I've found is using dependency-lock-maven-plugin.
My project has multiple maven modules.
parent
core
service
third-maven-module
When I run mvn clean package it will generate a new core-0.0.1-SNAPSHOT.jar every time.
Now apart from checking version dependency-lock-maven-plugin also checks SHA, which in this case gets changed every time & then the plugin throws error stating SHA is different.
Now to avoid this in plugin's version 0.0.78f56707b3a1d639c8e769bba1686587e9a8956 we can simple add below lines:
<configuration>
<ignore>
<dependency>com.myservice:core:*</dependency>
</ignore>
</configuration>
It works but now I can see that this version has vulnerabilities, so I want to use the latest version 1.0
But it looks like the configuration to ignore a dependency has been changed & documentation does not says much.
Please suggest how can I ignore a dependency in dependency-lock-maven-plugin.

JSON files formatting in Spring boot based projects

I have spring boot projects with lots of files in .json apart from .java files.
For java formatting, we are using pre-commit hooks with google-java-format . However, for formatting .json files I am a bit struggling.
I have used a maven spotless plugin
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.version}</version>
<configuration>
<formats>
<format>
<includes>
<include>*.json</include>
</includes>
<prettier>
<!-- Specify at most one of the following 3 configs: either 'prettierVersion' (2.0.5 is default) , 'devDependencies' or 'devDependencyProperties' -->
<prettierVersion>2.0.5</prettierVersion>
<!-- Specify config file and/or inline config, the inline always trumps file -->
<config>
<useTabs>true</useTabs>
</config>
</prettier>
</format>
</formats>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
The problem with this approach is, that it requires npm in the machine to be installed else mvn clean install will fail. Many machines on the jenkins server don't have npm pre-installed so it fails during the build.
Is there an easy way to solve this?
PS: This project uses GIT as version control here.
Introduction
Let's consider the limitation: the Spotless formatter steps must be Java-based, i.e. avoid using external programs (npm, etc.).
Let's consider Spotless Maven plugin 2.23.0 as the current version.
Let's call Java-based JSON document formatting and validation the feature.
Analysis
According to the feature matrix table, the following formatter steps are available for Spotless Gradle plugin, but not available for Spotless Maven plugin:
json.gson.GsonStep.
json.JsonSimpleStep.
These feature steps are Java-based.
Summary
Currently, there are no such Spotless formatter steps available for Spotless Maven plugin — the feature is absent.
Possible solutions
Implement feature
Implement the feature.
Create a pull request to propose and collaborate on changes to the GitHub repository.
Request feature
Request the feature by creating an issue in the GitHub repository.
It looks like there was a quick attempt to request it. Please, see the comment:
GitHub issue: Add JVM-based JSON formatter by jamietanna · Pull Request #853 · diffplug/spotless.
Comment.
Find and use additional formatter Maven plugin
Find and use additional formatter Maven plugin that has the feature.
For example, it seems that the following formatter Maven plugin supports JSON document formatting and validation:
<dependency>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.19.0</version>
</dependency>
Some related references:
formatter-maven-plugin – Introduction.
formatter-maven-plugin – formatter:format - configJsonFile parameter.
formatter-maven-plugin – formatter:validate - configJsonFile parameter.
formatter-maven-plugin/JsonFormatter.java at formatter-maven-plugin-2.19.0 · revelc/formatter-maven-plugin.
formatter-maven-plugin/JsonFormatterTest.java at formatter-maven-plugin-2.19.0 · revelc/formatter-maven-plugin.

Maven-dependency-plugin and annotations with SOURCE RetentionPolicy

In a mvn project where I am utilizing maven-dependency-plugin to detect unused dependencies, there is seemingly no dependency scope I can specify for Google's AutoValue (com.google.auto.value:auto-value) to that will convince the plugin that the dependency is being used in spite of the fact that annotations from the package are being used (e.g. #AutoValue) and the project won't build if auto-value is excluded.
Now one solution is simply adding a configuration entry to my plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<usedDependencies>
<usedDependency>com.google.auto.value:auto-value</usedDependency>
</usedDependencies>
</configuration>
</plugin>
But I would be curious to know whether it's possible to configure either the maven-dependency-plugin or the dependency entry for auto-value in a way that would detect usage of the dependency per its annotations?
My suspicion is that this isn't possible because the RetentionPolicy of the annotations I'm using from auto-value are of RetentionPolicy.SOURCE and are discarded by the compiler. Is this correct?
Unfortunately, your suspicion is correct. The maven-dependency-plugin documentation specifically lists this as a concern here for source level annotations: http://maven.apache.org/shared/maven-dependency-analyzer/
Warning: Analysis is not done at source but bytecode level, then some cases are not detected (constants, annotations with source-only retention, links in javadoc) which can lead to wrong result if they are the only use of a dependency.
You can force AutoValue as used with usedDependencies as you have in your example or use the ignoredUnusedDeclaredDependencies configuration instead (which is what I did recently).
I don't believe it is possible to configure the dependency section to avoid this because maven doesn't provide a scope level that is compile only. I mark AutoValue with the provided scope to keep it out of any shaded jars I might make.
Lastly, you could write (or find if it exists) a custom dependency analyzer that takes source level annotations into account. See the documentation here http://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html#analyzer. Probably not worth the effort.

How do you debug annotation injectors when they just appear null?

I am currently working with CQ5/AEM, and we have an #Reference annotation that seems to act in a similar fashion to an injector annotation.
Our problem was that we had a misconfiguration in our POM file, which caused the injection to just fail.
We had to brute force change the POM file section by section to identify what was causing the problem. Brute force is obviously never the best approach.
What are the different methods in other frameworks such as spring, to debug annotative injectors when they fail?
Any advice would be greatly appreciated, as we are finding it a common enough problem.
Best regards,
Bayani
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<configuration>
<instructions>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
We fixed it after removing configuration.
However by setting the replicator dependency with scope of provided also solved it.
<dependency>
<groupId>com.day.cq</groupId>
<artifactId>cq-replication</artifactId>
<version>5.4.24</version>
<scope>provided</scope>
</dependency>
My core question is still, given that we only have #Reference being null to start with, would you have any suggestions for how to attack this problem given just a null on a reference?
#Reference is not specific to CQ, it's handled by the Apache Felix maven-scr-plugin to generate metadata for OSGi Declarative Services (DS).
You're not saying how the "injection just failed" in your case.
If your problem happens at build time, it's probably due to a misconfiguration of the maven-scr-plugin, in which case the DS metadata won't be generated correctly. That metadata is generated under target/scr-plugin-generated/OSGI-INF, you could check the files that are in there against the DS spec to check that they're correct. The syntax of the XML metadata files generated there is fairly simple and documented in the DS specs. Note also mvn -X which outputs debug information at build time, that might help troubleshoot such issues.
If on the other hand the build and DS metadata are ok but the reference isn't satisfied at build time, you can check via the OSGi console (under /system/console in Sling and CQ5) if the required OSGi services are present, and if not check the system logs for possible reasons or debug the service modules at the Java level.

PMD coulnd't find ruleset

I'm on creating a maven based java project, which contains the PMD maven plugin. I use my own rule set XML and it works like a charm, except two rule sets: the emptycode and the unnecessary: when I run the build, maven says: "can't find resource". The role definitions look like:
<role ref="rulesets/emptycode" />
and
<role ref="rulesets/unnecessary" />
In every other cases, this kind of definition works. What I found out is that: there is a rule set with the name "unnecessary" under ecmasrcipt category, so maybe this definition needs some suggestion to use java version. I tried multiple thinks, like set language attribute to the ruleset xml node ("JAVA", based on PMD JavaDoc), and some pre-postfix in ref, but it doesn't work and I found no working solution over the web. Does someone has an idea, what I forgot to set, or what I fail? Thanks for any help!
PMD seems to be a fiddly beastie to use from Maven. I've just figured this out with version 3.0 of the plugin - there are two solutions:
The quick-and-dirty solution: put rulesets in your project:
download the PMD jar (http://sourceforge.net/projects/pmd/files/latest/download)
extract lib/pmd-x.x.x.jar
extract from that PMD jar file the rulesets/<type>/<ruleset>.xml files you want to use
place them in a folder under your project - something like ${basedir}/pmd/...
reference them as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<rulesets>
<ruleset>${basedir}/pmd/<ruleset>.xml</ruleset>
</rulesets>
</configuration>
</plugin>
The advantage is this is easy, the disadvantage is if you update the PMD version in future you'll need to remember to update these files.
The nice solution: reference rulesets in pmd-x.x.x.jar.
create a custom ruleset such as: ${basedir}/pmd/custom.xml (see http://pmd.sourceforge.net/pmd-5.0.2/howtomakearuleset.html)
reference the PMD rulesets in the following way: <rule ref="rulesets/java/imports.xml"/>
NB: the path is the path inside pmd-x.x.x.jar (see quick-and-dirty above) with no leading slash
reference your custom ruleset as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<rulesets>
<ruleset>${basedir}/pmd/custom.xml</ruleset>
</rulesets>
</configuration>
</plugin>
The advantage is this will always reference the current PMD rulesets from the PMD jar, the disadvantage is it's a bit fiddly to get right.
To experiment with this until it was working (maven-pmd-plugin version 3.0) I kept running mvn pmd:pmd (<linkXref>false</linkXref> in pom.xml) and tweaked the paths until I stopped getting errors.

Categories

Resources