Gradle XJC generate equals and hashCode methods - java

The project has a gradle module to build JAX2B classes.
The XJC configuration already uses annotations:
bindingFiles = project.files("$projectDir/src/main/resources/binding.xjb",
"$projectDir/src/main/resources/annotations.xjb")
// Needed to execute custom annotations
options.add("-Xannotate")
}
I thought I could add options to get equals() and hashCode()
xjc {
bindingFiles = project.files("$projectDir/src/main/resources/binding.xjb",
"$projectDir/src/main/resources/annotations.xjb")
options.addAll("-Xannotate", "-Xequals", "-XhashCode")
}
The methods are not on the class and there are no errors or warnings in the build log.
How do I generate those methods?
PS: Here are the build file dependencies
dependencies {
implementation(project(":xxx:xxx-api"))
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.11.2")
xjcPlugins("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.11.2")
xjcPlugins("org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.1.0")
}
UPDATED
Thanks to #thokuest for spotting a missing dependency.
The project has a gradle module to build JAX2B classes, but I'm getting build errors adding the "-Xequals" option:
build/generated/sources/xjc/java/org/pen/ProductOutputType.java:16: error: package org.jvnet.jaxb2_commons.locator.util does not exist
import org.jvnet.jaxb2_commons.locator.util.LocatorUtils;
^
build/generated/sources/xjc/java/org/pen/ProductOutputType.java:47: error: cannot find symbol
public class ProductOutputType implements Equals2
^
I've created a minimum example as a gist -- build.gradle.kts

equals() and hashCode() are contributed by the jaxb2-basics plugin.
xjcPlugins 'org.jvnet.jaxb2_commons:jaxb2-basics:1.11.1'
According to the project's wiki, there's a runtime dependency to org.jvnet.jaxb2_commons:jaxb2-basics-runtime:1.11.1 that you would need to add as well.
Update
Dependency org.jvnet.jaxb2_commons:jaxb2-basics-runtime:1.11.1 must be in scope implementation as otherwise a build error as described in the question occurs.

Related

How to add com.fasterxml.jackson.core.exc.InputCoercionException as a dependency in gradle?

I am getting java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/PropertyNamingStrategies which is used in another project. I have included jackson jar in current gradle project as well. But while starting the project I am getting the above mentioned error. Seems like we need to add com.fasterxml.jackson.core.exc.InputCoercionException as an dependency but I am not able to understand where to add this as a dependency ? Can someone please help ?
java.lang.NoClassDefFoundError Either means - missing dependency with class com/fasterxml/jackson/databind/PropertyNamingStrategies or class was removed meaning jackson libs versions used in your project dependencies won't work together.
How to start solving problems like those.
1, Via IDE try to find missing class if is present. If is not present then try to find jar with missing class on internet and add as dependency. In case your IDE show class is present then problem may be with import scope. Scope management differ per used technology so provide detail which one you use or paste dependencies from build.kts . Make sure you use implementation in case you import this class in project and not runtimeOnly.
2, You found class then try to print project dependency tree command differ per used technology. For gradle ./gradlew dependencies or for submodule ./gradlew submoduleName:dependencies and look at versions of jackson in your project.
3, Check jackson lib with version listed via dependency tree contains missing class.
How to avoid problem like those with spring boot.
I would recoment to use BOM provided by spring boot project, versions in there should work together.
For gradle with kotlin DSL we import it like this
import org.springframework.boot.gradle.plugin.SpringBootPlugin
plugins {
id("org.springframework.boot") version "2.6.2"
}
dependencies {
val springBootPlatform = platform(SpringBootPlugin.BOM_COORDINATES)
annotationProcessor(springBootPlatform)
implementation(springBootPlatform)
//this version has to be searched for spring boot version
implementation(platform("org.springframework.cloud:spring-cloud-dependencies:2021.0.0"))
//put desired jackson dependencies
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
}

Gradle test fixtures plugin and core module dependencies

I have a project built with Gradle version 6.4 and JDK 8. I'm trying to use the Gradle plugin for Test Fixtures (java-test-fixtures) but I have some issues with the dependencies.
According to the Gradle page linked above, the project should be structured like this:
core-module
-- src
-- main
-- java
-- test
-- java
-- testFixtures
-- java
While the build.gradle.kts file has the following dependencies section:
dependencies {
api("com.my.external.project:1.0")
// ... more API dependencies
testFixturesCompileOnly(project(":core-module"))
testFixturesApi("junit:junit:4.12")
// ... more test dependencies
}
Now, in IntelliJ (the IDE I'm using) classes in the testFixtures/java source folder see the classes in the main/java source folder. So I can add new Java classes under testFixtures/java that have dependencies on those under main.
However, I won't be able to import the dependencies from the external library com.my.external.project:1.0. The problem is confirmed when I try to run the Gradle task compileTestFixturesJava.
I can duplicate the entry in the dependencies section; e.g. I can add:
testFixturesImplementationOnly("com.my.external.project:1.0")
But that is not really what I expect to do; especially when I have dozens of dependencies.
I could also define the dependencies in an array and run a for-each over them. Still, this is not the cleanest solution.
Is there a clean solution that will allow the testFixtures module to use the dependencies declared in the main module?
Most important concept in the Gradle java-test-fixtures plugin is stated in their documentation:
[this plugin] will automatically create a testFixtures source set, in which you can write your test fixtures. Test fixtures are configured so that:
they can see the main source set classes
test sources can see the test fixtures classes
This plugin will indeed create the following dependencies: main <-- testFixtures , and testFixtures <-- test
In your case, testFixtures module should automatically depend on main sources, and also on main dependencies declared in api scope ( com.my.extenal.project:1.0)
See a similar example in a valid sample project here https://github.com/mricciuti/so-64133013 :
Simpsons class has access to Person class from main module
TestHelpers class has access to main dependencies declared in api configuration
Note that testFixtures will not inherit dependencies from the test module: if you need to use such libraries in this module (eg. JUnit, Mockito, ...) you will need to declare explicit dependency , using testFixturesImplementation or testFixturesApi configuration.
See example in core-module
plugins {
id ("java-library")
id ("java-test-fixtures")
}
dependencies {
// Main dependencies
// will be available in "testFixture" as well thanks to "api" configuration
api("org.apache.commons:commons-lang3:3.9")
api(project(":utils-module"))
// Testfixture dependencies
// ==> mockito lib will be available in testFixture module and also in consumer modules (e.g test)
testFixturesApi("org.mockito:mockito-core:3.5.13")
// Test dependencies
// dependencies specific to the "test" module; not visible from "testFixtures"
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.3.1")
}

Implement custom modules for checkstyle

I've created a plugin which invokes the Checkstyle plugin for all the sub projects in a project. Executing simple checkstyle rules against any of the projects works fine, but when I introduce my custom Module, the build process throws up
Caused by: com.puppycrawl.tools.checkstyle.api.CheckstyleException: Unable to instantiate 'com.test.gradle.plugin.perf.MethodLimitCheck' class
This class has the custom rule, that I want checkstyle to run. My plugin gets triggered during the build of the project and tries to run this custom module where it fails. Tried going through a lot of online resources but couldn't find anything. I'm using Checkstyle version 8.17.
Why is the other project not able to instantiate the class? Even when the class is a part of the plugin jar, which is attached to the other project ?
What is the correct way to attach a custom module ?
For Gradle, custom checks must be placed on the classpath of the analysis run by adding the custom check to the checkstyle configuration. Example from the Checkstyle Addons library (basically a collection of custom checks):
plugins {
id 'checkstyle' // regular Checkstyle plugin
}
dependencies {
checkstyle group: 'com.thomasjensen.checkstyle.addons', name: 'checkstyle-addons', version: '5.2.2'
}
checkstyle {
configFile file('your-checkstyle.xml')
toolVersion '8.0' // set Checkstyle version here
}

Eclipse AutoValue class fails to build

I'm running Eclipse Kepler SR2, with Maven 3.1.1 attached with the m2e and m2e-apt plugins, and I'm getting an error I don't know how to resolve.
I managed to find all the dependencies needed to get #AutoValue working into my pom.xml, but now I'm in a state where it only works if the methods which need to be defined all have primitive return types. If I provide an abstract getter which returns an Object or more specific, I get this error:
#AutoValue processor threw an exception:
java.lang.IllegalArgumentException:
Failed to invoke com.google.auto.value.processor.AutoValueProcessor$Property.nullable() on getObject...
I've tried the basics - cleared the maven cache, restarted Eclipse, rebuilt the project... no dice. So I dug down into the source code and I found a discrepancy which I'm not sure how it's intended to be resolved.
In the Velocity template for the generated AutoValue class, there is some basic logic for rendering primitives differently than objects, for instance on line 37, p.nullable is checked. The p variable is an instance of AutoValueProcessor$Property class, which, as can be seen on line 205 of the preceeding link, has an isNullable() method, but no nullable method or property.
How is the Velocity rendering phase intended to work then? Does Velocity auto-expand p.nullable to p.isNullable some how, but not for me because reasons? Is this a bug? I'm not sure what to do from here.
Example class that doesn't compile:
#AutoValue
public abstract class Point {
public static Point of(double x, double y) {
return new AutoValue_Point(x, y);
}
public abstract Double x();
public abstract Double y();
}
Eclipse highlights the described error under Point at the head of the class declaration.
It appears that the dependency com.google.code.findbugs:jsr305 is missing when Eclipse runs the annotation processor. Try adding it by opening the project properties, browsing to Java Compiler -> Annotation Processing -> Factory Path, clicking on "Add External JARs" and then selecting the jsr305 JAR. If you have built the project with maven from the command line, you should be able to select the JAR from your .m2 directory.
Here's what the proprties look like in my project (the first entry is automatically added by Eclipse and doesn't seem to be relevant):
In the pom.xml in version 1.0-rc1 of AutoValue, there is a comment "Must have this where procesor runs" at the jsr305 dependency. The dependency was removed after the release of 1.0-rc1, so adding it to the annotation processor factory path will probably not be necessary with version 1.0.
See also this blog post for an introduction to using AutoValue with Eclipse.
You might want to install the m2e-apt plugin, which handles automatic annotation processing based on the pom.xml dependencies:
https://marketplace.eclipse.org/content/m2e-apt
Make sure to enable it in you project preferences or globally in section:
Maven -> "Annotation processing" -> select "Automatically configure JDT APT..."
Detailed info here and here.

How to allow user to change the version of the library which is used by a plugin in Gradle?

In my plugin I call static bootstrapping method MutationCoverageReport.main(arg) from a library which is a compile dependency of my plugin. I would like to allow a plugin user to change the version of the library which should be used (assuming the selected version has compatible API).
I could advice user to exclude a transitive dependency from my plugin and add a dependency to the library in the requested version manually to buildscript.dependencies.classpath in his build.gradle, but this is not very elegant:
buildscript {
(...)
dependencies {
classpath('info.solidsoft.gradle.pitest:gradle-pitest-plugin:0.32.0') {
exclude(group: 'org.pitest')
}
classpath 'org.pitest:pitest-command-line:0.33'
}
}
I would like to be able to use libVersion parameter in my configuration closure, but I have some problems with two solutions I tried.
1. I could need to remove transitive dependencies from my plugin (an original library version and its dependencies) and add a library in requested version (from configuration closure) as a buildscript dependency.
In afterEvaluate it is to late (configurations are resolved) and I had problem to successfully hook with beforeEvaluate (is it triggered for single module project?).
2. I could change a classpath which is used to execute a static method from a library.
To do that I could create a custom class loader which would use my library classes (in requested version) before delegating to the parent class loader. I also would have to replace one liner with MutationCoverageReport.main(arg) with the reflection call using the new class loader.
Maybe there is a simpler way to modify a classpath by a plugin with which the mentioned method will be called?
Main questions. What would be the best way to allow plugin users to define the version of the library the plugin executes?
I'm not sure this is what you're looking for, but here's how the Jacoco plugin allows the user to configure the library being used.
JacocoPluginExtension
class JacocoPluginExtension {
// ...
String toolVersion = '0.32.0'
// ...
}
JacocoPlugin
class JacocoPlugin implements Plugin<Project> {
// ...
config.dependencies.add(this.project.dependencies.create("org.jacoco:org.jacoco.ant:${extension.toolVersion}"))
// ...
}
In another question about executing Java class with a separate classpath Peter Niederwieser provided 3 approaches. In the end modify my task to extend JavaExec. I set explicit set execution classpath which is separate from plugin execution classpath and can contain different library version.
The drawback is allows only to run main method, but it wasn't a problem in my case.

Categories

Resources