JOOQ Code Generation Before Source Code Compilation - java

I am using JOOQ code generation Tool for generating source code for my schema(MYSQL). I would like to generate source code every time I compile my Project. But I am not able to do it because when I run Code generation gradle Task, Compiler starts complaining about references of deleted source code.
Here is what I did:-
Created an Empty Spring boot Project.
Generated Source code using config xml(jooq.xml below) like this
Triggered Code Generation using a Gradle Task.
Build.gradle
task generateJooqDatabaseSource(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jooq.util.GenerationTool'
args = ['/jooq.xml']
standardOutput = System.out
errorOutput = System.err
}
Used the generated source code and wrote SQLs using JOOQ.
Everything is fine till here. But now I don't want to Push the generated Java Classes to my Project. I would like it to create every time when I compile my Project.
so lets delete the generated source code and re-generate it again(say for my Test environment)
But as soon as I run the Gradle Task generateJooqDatabaseSource
it starts complaining about the generated code references.
error: package autogenered.jooq.code.db.tables does not exist
import autogenered.jooq.code.db.tables.Author;
Tried googling the problem and found suggestions to use plugins like flyway, suggested here
But I really don't want to add another plugin if it can be achieved easily without it.
PS:- Just started to use Gradle, JOOQ from couple of days, apologies if answer is obvious.

Adding Following Lines in build.gradle have done the tweak for me:
compileJava.dependsOn(generateJooqDatabaseSource)
generateJooqDatabaseSource.dependsOn = [processResources, processTestResources]
Intellij Specific configuration:-
Added gradle build task to be triggered every time I do
make Project (Ctrl-F9)
or
Re-build Project:

Related

Exposing a dependency with a gradle build

My product is using a third party dependency called matlab control version 4.1.0. This jar file allow java to send command to matlab.
The way we use it is by calling a java command in matlab (triggered by the user), this perform a bunch of computation in the java plugin, then java sends a notification to matlab which then start executing m code with data received from java.
So far, the jar file is stored in our repository, and directly loaded in matlab.
We want to move to matlab-control v5.0.0, which is on maven. So we thought it was the occasion to get rid of the jar file, include it as a dependency from maven in our gradle build.
However the api seems to not be visible to Matlab, which returns an exception 'can not find class org.n52.matlabcontrol.MatlabProxy'.
If I test the connection directly from java (by creating a java test), java will by itself launch matlab and request the command to be executed (for instance, an hello world command). It's working fine, and I can then instantiate a MatlabProxy. But if I launch Matlab and try to access the MatlabProxy directly from it, it cannot find it.
So it seems that the Matlab-control API is not exposed by my gradle build. So far I have tried the following:
apply plugin: 'java-library'
dependencies {
implementation('org.n52.matlab:matlab-control:5.0.0')
api('org.n52.matlab:matlab-control:5.0.0')
}
But it is not working, so what I am missing ?
Thanks to JB Nizet who put me in the right direction, I found a solution.
I just had to create a configuration first, then assign dependencies to this configuration in order to copy them:
configurations {
deployerJars
}
dependencies {
deployerJars group: 'org.n52.matlab', name: 'matlab-control', version: '5.0.0'
}
task copyToLib(type: Copy) {
into "$buildDir/libs"
from configurations.deployerJars
}

Gradle + Eclipse : use class from existing project in a new project

I know there are a lot of questions that seem similar. I have also spent a few hours getting to grips with Gradle multiprojects. But I still don't understand what the best course of action is here. Incidentally I am using Groovy as my coding language, but explanations referencing Java would be just as good.
I have developed an Eclipse Gradle project, "ProjectA", which in particular has a class, IndexManager, which is responsible for creating and opening and querying Lucene indices.
Now I am developing a new Eclipse Gradle project, "ProjectB", which would like to use the IndexManager class from ProjectA.
This doesn't really mean that I would like both projects to be part of a multiproject. I don't want to compile the latest version of ProjectA each time I compile ProjectB - instead I would like ProjectB to be dependent on a specific version of ProjectA's IndexManager. With the option of upgrading to a new version at some future point. I.e. much as with the sorts of dependencies you get from Maven or JCenter...
Both projects have the application plugin, so ProjectA produces an executable .jar file whose name incorporates the version. But currently this contains only the .class files, the resource files, and a file called MANIFEST.MF containing the line "Manifest-Version: 1.0". Obviously it doesn't contain any of the dependencies (e.g. Lucene jar files) needed by the .class files.
The application plugin also lets you produce a runnable distribution: this consists of an executable file (2 in fact, one for *nix/Cygwin, one for Windows), but also all the .jar dependencies needed to run it.
Could someone explain how I might accomplish the task of packaging up this class, IndexManager (or alternatively all the classes in ProjectA possibly), and then including it in my dependencies clause of ProjectB's build.gradle... and then using it in a given file (Groovy or Java) of ProjectB?
Or point to some tutorial about the best course of action?
One possible answer to this which I seem to have found, but find a bit unsatisfactory, appears to be to take the class which is to be used by multiple projects, here IndexManager, and put it in a Gradle project which is specifically designed to be a Groovy library. To this end, you can kick it off by creating the project directory and then:
$ gradle init --type groovy-library
... possible to do from the Cygwin prompt, but not from within Eclipse as far as I know. So you then have to import it into Eclipse. build.gradle in this library project then has to include the dependencies needed by IndexManager, in this case:
compile 'org.apache.lucene:lucene-analyzers-common:6.+'
compile 'org.apache.lucene:lucene-queryparser:6.+'
compile 'org.apache.lucene:lucene-highlighter:6.+'
compile 'commons-io:commons-io:2.6'
compile 'org.apache.poi:poi-ooxml:4.0.0'
compile 'ch.qos.logback:logback-classic:1.2.1'
After this, I ran gradle jar to create the .jar which contains this IndexManager class, initially without any fancy stuff in the manifest (e.g. name, version). And I put this .jar file in a dedicated local directory.
Then I created another Gradle project to use this .jar file, the critical dependency here being
compile files('D:/My Documents/software projects/misc/localJars/XGradleLibExp.jar' )
The file to use this class looks like this:
package core
import XGradleLibExp.IndexManager
class Test {
public static void main( args ) {
println "hello xxx"
Printer printer = new Printer()
IndexManager im = new IndexManager( printer )
def result = im.makeIndexFromDbaseTable()
println "call result $result"
}
}
class Printer {
def outPS = new PrintStream(System.out, true, 'UTF-8' )
}
... I had designed IndexManager to use an auxiliary class, which had a property outPS. Groovy duck-typing means you just have to supply anything with such a property and hopefully things work.
The above arrangement didn't run: although you can do build and installdist without errors, the attempt to execute the distributed executable fails because the above 6 compile dependency lines are not present in build.gradle of the "consumer" project. When you put them in this "consumer" Gradle project's build.gradle, it works.
No doubt you can add the version to the generated .jar file, and thus keep older versions for use with "consumer" projects. What I don't understand is how you might harness the mechanism which makes the downloading and use of the dependencies needed by the .jar as automatic as we are used to for things obtained from "real repositories".
PS in the course of my struggles today I seem to have found that Gradle's "maven-publish" plugin is not compatible with Gradle 5.+ (which I'm using). This may or may not be relevant: some people have talked of using a "local Maven repository". I have no idea whether this is the answer to my problem... Await input from an über-Gradle-geek... :)
You should be able to update the Eclipse model to reflect this project-to-project dependency. It looks something like this (in ProjectB's build.gradle):
apply plugin: 'eclipse'
eclipse {
classpath.file.whenMerged {
entries << new org.gradle.plugins.ide.eclipse.model.ProjectDependency('/ProjectA')
}
project.file.whenMerged {
// add a project reference, which should show up in /ProjectB/.project's <projects> element
}
}
These changes may be to the running data model, so they may not actually alter the .classpath and .project files. More info can be found here: https://docs.gradle.org/current/dsl/org.gradle.plugins.ide.eclipse.model.EclipseModel.html
This issue is discussed here: http://gradle.1045684.n5.nabble.com/Gradle-s-Eclipse-DSL-and-resolving-dependencies-to-workspace-projects-td4856525.html and a bug was opened but never resolved here: https://issues.gradle.org/browse/GRADLE-1014

Gradle - Executing custom annotation processor during compile time

I have a custom annotation processor (that extends AbstractProcessor) which adds a properties file to the project based on the annotations. I want this to be run everytime when a compilation is happening. The project is a java project using gradle.
How do I get the annotation processor run during compile time? Should I use some compiler plugin? or should I write a simple gradle task that can invoke this annotation processor and make that task part of the compilation task? (I'm a beginner with gradle)
In the META-INF/services, added the entry for javax.annotation.processing.Processor specifying the custom annotation processor class.
I know that this question is quite old but since it even got a favor and nobody answered it I want to give at least a little answer for future readers.
For this are multiple ways possible depending on the way your environment is set up.
For example you can use something like this in build.gradle or some other .gradle file that is used by all wanted projects:
compileJava{
options.fork = false
options.forkOptions.executable = 'javac'
options.compilerArgs.addAll(['-classpath','path/to/your/compiled/processor.jar'])
}
when you use the dependency system you could use this:
dependencies {
compileClasspath group: 'com.company', name: 'AnnotationProcessor', version: 'your revision'
//or this
compileClasspath 'com.company.AnnotationProcessor:revision'
}
but be sure to have the .Processor file in src/main/resources/META-INF/services for this method. Else you would have to add the compilerArg '-processor','full.package.name.with.class.name' <-- this could be wrong since I never tried that way.
The only way I could get annotations to work was via setting the -processorpath directly.
compileJava{
options.compilerArgs.addAll(['-processorpath',"$rootDir/yoursubproject/annotation.jar"])
options.compilerArgs.addAll(['-Acom.crd.whomever.processors.pass=Production'])
options.compilerArgs.addAll(['-XprintRounds'])
options.compilerArgs.addAll(['-XprintProcessorInfo'])
}

Annotation processor in Gradle outputs source files to build/classes making javadoc fail. How to fix it?

I have an annotation processor that is automatically picked up by the Java compiler at build time (using SPI). During a gradle build, the generated java sources of this annotation processor are put in build/classes as Gradle tells the annotation processor that this is the place to output generated source files.
When the standard javadoc task is run, it tries to create javadoc for all files in build/classes, including *.java. This failes because javadoc only expects *.class files, making the whole build fail.
So my question is:
Is this a Gradle bug/feature?
How do I fix it/make it work?
It seems the problem is that the generated source files are not picked up, making the javadoc fail because it had nothing to process.
I'm posting the solution here in case somebody is experiencing the same problem:
The problem with compile time source generation in gradle is that the outputted sources are not automatically picked up by the javadoc. This is a problem if all your sources are auto generated. The build will fail with an error saying that no sources could be processed. In the other case your build will succeed but you will have no javadoc of your generated java sources.
The root problem here is gradle's poor integration with generating sources that are both generated and compiled during the same compile step. To remedy this I changed my build files to this.
project layout:
rootproject
rootproject/annotationProcessor
rootproect/userOfAnnotationProcessor
build file of userOfAnnotationProcessor
def generatedSources = "$buildDir/generated-src"
def generatedOutputDir = file("$generatedSources")
compileJava {
doFirst {
generatedOutputDir.exists() || generatedOutputDir.mkdirs()
options.compilerArgs = [
'-s', "${generatedSources}"
]
}
}
sourceSets {
main {
java {
srcDirs += generatedOutputDir
}
}
}
javadoc {
source = sourceSets.main.resources
}
compileJava.dependsOn clean
The trick here is to not add your generated sources to a custom sources set, else we'll run into troubles when trying to build aggregated javadoc in our root project. However this solution has the nasty side effect that our generated sources or added twice for some reason when trying to build after a first clean+build. The solution here is to always do a clean+build.
Now when doing an aggregate javadoc build, we'd like our generated source javadoc to be part of it as well.
This is how our rootproject build file looks like:
def exportedProjects = [
":annotationProcessor",
":userOfAnnotationProcessor",
]
task alljavadoc(type: Javadoc) {
source exportedProjects.collect { project(it).sourceSets.main.allJava }
classpath = files(exportedProjects.collect { project(it).sourceSets.main.compileClasspath })
destinationDir = file("${buildDir}/docs/javadoc")
}
alljavadoc.dependsOn(":userOfAnnotationProcessor:compileJava")
If we had used a custom source set previously, gradle would now start complaining about source set properties not being found. Why? I don't know... A last important thing to notice is that our alljavadoc depeonds on the compilation step of userOfAnnotationProcessor, this is needed to make sure our generated source files are there when the aggregated javadoc is build.
I hope I've helped sombody with this explanation!
I am not quite sure weather it is a bug or not. But as a workaround just filter the sources of javadoc.
Depending on how your build script looks like, it should look something like thistask
myJavadocs(type: Javadoc) {
classpath = sourceSets.main.output.filter { it -> !it.name.endsWith('.java') }
}

Gradle - how to run the tests from a different gradle project and still get coverage data

Does anyone know how to run the tests from a different gradle project and still get emma coverage reporting data?
Here is my current layout:
Root/
settings.gradle (no explicit build.gradle - just defines all subprojects)
SubProjectA/
build.gradle
src/ (all real source is here)
SubProjectATest/
build.gradle
src/ (all testing code is here)
SubProjectB/ (similar structure as A)
SubProjectBTest/ (similar structure as ATest)
I am currently using the emma plugin, and I would like to build SubProjectA and run all the tests in SubProjectATest from within the build.gradle of SubProjectA.
Here are some things I tried inside the build.gradle of SubProjectA
testCompile project(':SubProjectATest').sourceSets.test.classes (as suggested by this article), but I got an error "Could not find property 'sourceSets' on project"
Just the straight-up testCompile project(':SubProjectATest'), but then I get "..SubProjectA/build/classes/test', not found" and also "Skipping task ':SubProjectA:compileTestJava' as it has no source files."
Simply adding a sourceSet like the following:
test {
java {
srcDir '../SubProjectATest/src'
}
}
Adding the source set in (option 3) is the only option that worked, but it seems sloppy to do it this way. Does anyone know how to do this using project dependencies?
Update #1
I also tried one of the answers below to use test.dependsOn and the tests do run, but the emma plugin reported the following: build/classes/test', not found
1. and 2. just add classes to the test compile class path. This doesn't have any effect on which tests are going to be executed.
3. is the wrong approach because you should not add sources from project X to project Y.
If what you want is that gradle :SubProjectA:test also executes :SubProjectATest:test, all you need to do is to add a task dependency:
SubProjectA/build.gradle:
test.dependsOn(":subProjectATest:test")
By the way, what is your motivation for putting the tests in a separate project?

Categories