Tuesday, September 10, 2013

Suppressing PMD alerts for Lombok generated code

As you know from my previous post, Lombok offers Java programmers a convenient equivalent to Scala's Case Classes. And the lombok-maven-plugin allows for easy integration of Lombok into a Maven project.

I am a big fan of Static Code Analysis tools like PMD and FindBugs. Generally, one could argue that it is not necessary to run checks against generated code because it is not the source code that you are maintaining. For code generation tools like ANTLR, I think skipping checks is prudent because if the generated code does not comply with your quality standards, there may be little that one can do — the source code that should be scrutinized is the ANTLR grammar.

When using Lombok, the tool may generate some boiler-plate code for you, like getters, setters, equals, and hashCode, but you often write some additional methods that you would want to have PMD analyze. As a result, excluding PMD from processing your classes is not recommended. And then you get second thoughts after seeing the consequences of running PMD against a generated equals and hashCode implementation, complaining about missing braces, multiple exit points, complexity, etc. Worse is that all that crying wolf makes it hard to focus on the real problems that you need to address.

You may notice, however, that Lombok always adds an annotation to generated code:

@java.lang.SuppressWarnings("all")
This annotation is supposed to hint to tools that this code can be ignored because it is generated.

Prior to PMD 5, you could suppress PMD for a class or a line, but not for a method. PMD 5 offers two new suppression techniques, one of which we can leverage for suppressing checks against Lombok code: Violation Suppress XPath.

Certain rules have a tendency to fire false alarms for Lombok generated code:

For these rules, we can add an XPath expression for the Suppress Warnings annotation so that those rules will be skipped for Lombok generated methods.

The XPath expression for the Suppress Warnings annotation is:

//MethodDeclaration[../Annotation/SingleMemberAnnotation[ (Name/@Image='java.lang.SuppressWarnings') and (MemberValue/PrimaryExpression/PrimaryPrefix/Literal/@Image='"all"')]]

The rule can be configured with the Violation Suppress XPath like this:

<rule
  ref="rulesets/java/braces.xml/IfStmtsMustUseBraces">
  <properties>
    <property name="violationSuppressXPath"
      value="//MethodDeclaration[../Annotation/SingleMemberAnnotation[
(Name/@Image='java.lang.SuppressWarnings') and (MemberValue/PrimaryExpression/PrimaryPrefix/Literal/@Image='"all"')]]" />
  </properties>
</rule>

The Sample Maven Lombok Project has been enhanced to demonstrate this.

Monday, September 2, 2013

Mavenizing the Flex SDK - The Missing Documentation

For those of us using Maven and Flex, we need to get the Flex artifacts uploaded to a Maven repository. In my case, I have an Artifactory instance that can house corporate artifacts and third-party artifacts, and proxy artifacts available on the internet.

The Apache Flex project has a couple of SDK utilities that greatly help moving all the necessary artifacts into a Maven repository. Specifically:

  1. Apache Flex SDK Installer
  2. Apache Flex SDK Mavenizer

The Apache Flex SDK Installer is a download utility that will simplify pulling down Adobe AIR, Flex SDK, and Flash Player. After installing the installer, run it to select the versions that you want to download. For my case, I downloaded:

  • Flex SDK 4.10.0
  • AIR 3.8
  • Flash Player 11.8
I specified an empty installation directory that I created first (C:\temp\apache\flexsdk), checked all the the license agreements, and then clicked on Install.

The Apache Flex SDK Mavenizer seems to only be available in source-code form. It can be downloaded using either Subversion or Git:

Subversion
https://svn.apache.org/repos/asf/flex/utilities/trunk/mavenizer/
Git
https://git-wip-us.apache.org/repos/asf/flex-utilities.git

Checkout (Subversion) or Clone (Git) the project, then build it using maven. For example:

C:\temp\apache\mavenizer> mvn package

The Apache Flex SDK Mavenizer has the following usage:

java -cp target/flex-sdk-converter-1.0.jar SDKGenerator "[sdkhome]" "[fdktarget]" false
where the sdkhome directory is structured like:
[sdkhome]
  +- air
    +- AdobeAIRSDK-[Airversion]
  +- flex
    +- flex_sdk_[Flexversion]

The Apache Flex SDK Installer downloads everything into one directory (C:\temp\apache\flexsdk), but the Apache Flex SDK Mavenizer expects the AIR SDK and the Flex SDK to be in different directories. Rather than trying to dissect the AIR SDK from the Flex SDK, the easiest solution is to duplicate the one directory so that it fits the necessary structure. For example:

C:\temp\apache> mkdir sdkhome
C:\temp\apache> mkdir sdkhome\air
C:\temp\apache> mkdir sdkhome\flex
C:\temp\apache> xcopy /s flexsdk sdkhome\air\AdobeAIRSDK-3.8\
C:\temp\apache> xcopy /s flexsdk sdkhome\flex\flex_sdk_4.10.0\

Next, create an empty target directory that will contain the artifacts in Maven format:

C:\temp\apache> mkdir fdktarget

Now you can run the SDK Generator step of the Apache Flex SDK Mavenizer:

C:\temp\apache\mavenizer> java -cp target\flex-sdk-converter-1.0.jar SDKGenerator "C:\temp\apache\sdkhome" "C:\temp\apache\fdktarget\" false
Note that the last argument is false as long as flexmojos-maven-plugin will be used; when maven-flex-plugin is used, then true will be specified.

Feel free to inspect the results of fdktarget. There are a lot of files -- too many to deploy manually to Artifactory. Luckily, the Apache Flex SDK Mavenizer utility has the SDK Deployer step that will upload these files to a repository. For example:

C:\temp\apache\mavenizer> java -cp target\flex-sdk-converter-1.0.jar SDKDeployer "C:\temp\apache\fdktarget\" flex-releases http://ArtifactoryHost/artifactory/third-party-releases-local/ "C:\apache-maven-3.0.4\bin\mvn.bat"

Note that flex-releases refers to a <server> entry in my Maven settings.xml that contains credentials for Artifactory. For example:

<settings>
  <servers>
    <server>
      <id>flex-releases</id>
      <username>awhitford</username>
      <password>super-secret</password>
    </server>
  </servers>
</settings>

There is a lot to upload, so be patient.