How to simulate a gradle build script in junit test? - java

I am playing a little bit with my own gradle plugin (for gradle 6.5.1). Now I wrote a small test (implemented in java) which is not working:
Project project = ProjectBuilder.builder().build();
ScriptHandler buildscript = project.getBuildscript();
Action<? super MavenArtifactRepository> action = new Action<MavenArtifactRepository>() {
#Override
public void execute(MavenArtifactRepository mavenArtifactRepository) {
mavenArtifactRepository.setUrl("https://plugins.gradle.org/m2/");
}
};
buildscript.getRepositories().maven(action);
buildscript.getDependencies().add("classpath", "io.spring.gradle:dependency-management-plugin:1.0.9.RELEASE");
project.getPlugins().apply("java");
project.getPlugins().apply("io.spring.dependency-management");
It says Plugin with id 'io.spring.dependency-management' not found. I thought that I copied the original from https://plugins.gradle.org/plugin/io.spring.dependency-management
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "io.spring.gradle:dependency-management-plugin:1.0.9.RELEASE"
}
}
apply plugin: "io.spring.dependency-management"
But I guess thats not the case. :-) Any idea how to translate that snippet to java world?

If you want to apply an other plugin in your test you need the other plugin on your classpath. So you have to add to the build file of your gradle-plugin and than its there.
In this case it means write the following to your build.gradle
testImplementation "io.spring.gradle:dependency-management-plugin:1.0.9.RELEASE"

Related

How to add custom module with package in gradle?

I'm unable to add custom source set in my gradle project. How to initialize the version numbers in here?
My gradle file looks like:
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
sourceSets {
demo
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
test {
useJUnitPlatform()
}
You can set custom sourceSets like this in your build.gradle
main {
java {
srcDirs = ['src/gen/java', 'src/main/java']
}
}
The srcDirs is an array, so you can specify more than one source directory.
You can also specify custom source directories for your tests
test {
java {
srcDirs = ['src/integrated-test/java', 'src/test/java']
}
}
You can find some more info here https://www.baeldung.com/gradle-source-sets in section 3. They use the example for integrated tests, but the idea is the same.
Here is the official gradle document for source sets https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html
I found a solution.
If your requirement is projectFolder/src/ -> Here you want to create a custom module other than the main and test. follow the below one.
Its worked in Intellj ide.
sourceSets {
customModuleName.java.srcDir "src/customModuleName"
customModuleName.resources.srcDir "src/customModuleName"
}
// After adding the above block in build file. Go ahead and create a directory, it will show a module name in suggestion
// Then inside module, Go to create a package. Here we can find java and resources folder in suggestion

Gradle custom plugin jar with dependencies

I'm trying to build a jar for a custom gradle plugin to be used by other gradle projects. I'm using java to write the plugin. I'm having a problem including dependencies in my jar. If I build the jar using the below build.gradle
plugins {
id 'groovy'
}
repositories{
mavenCentral()
}
dependencies {
compile gradleApi()
compile localGroovy()
compile 'com.google.guava:guava:27.0-jre'
testCompile 'junit:junit:4.12'
//compile 'org.apache.commons:commons-lang3:3.8.1'
}
group = 'com.mine'
version = '1.0'
I get a NoClassDefFound exception for guava classes when applying the plugin on a project. If I include a task to create a jar with dependencies like below in the build.gradle
jar {
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)}
}
}
It says Plugin with Id 'my-plugin' not found. How do I include dependencies in a gradle plugin jar?
Your plugin project should be configured as a standalone Plugin project and then published to a maven repository, which will make dependencies resolution work; there is good documentation about writing custom plugin here, specially the following part : using Gradle plugin development plugin
There is also a good example of writing/publishing/consuming a custom Plugin in the Gradle examples here : https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples/plugins (see the two subprojects publishing and consuming )
And here is a working example with a plugin that has dependency on external library (commons-lang for example):
Plugin project
build.gradle
plugins {
id 'java-gradle-plugin'
id 'groovy'
id 'maven-publish'
}
group 'org.gradle.sample.plugin'
version '0.1'
// pugin metadata configuration
gradlePlugin {
plugins {
myplugin {
id = "org.gradle.sample.plugin.myplugin"
implementationClass = "org.gradle.sample.plugin.MyPlugin"
}
}
}
// publish to local maven repo for testing
publishing {
repositories {
maven {
url "../repos/maven-repo"
}
}
}
// repo for dependences resolution
repositories{
jcenter()
}
// dependencies of this plugin
dependencies {
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
}
Plugin implementation : src/main/groovy/org/gradle/sample/plugin/MyPLugin.groovy
package org.gradle.sample.plugin
import org.apache.commons.lang3.StringUtils
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin implements Plugin<Project> {
#Override
void apply(final Project project) {
println "Applying custom plugin... "
project.tasks.create('testPlugin'){
doLast{
println " custom plugin task executing."
println "Result: " + StringUtils.capitalize("stringtotest")
}
}
}
}
Build and publish this plugin ./gradlew publish : the plugin jar and "plugin marker artefacts" will be published to local maven repo in ../repos/maven-repo
Consumer project
build.gradle
plugins {
id 'java'
// import/apply your custom plugin
id 'org.gradle.sample.plugin.myplugin' version '0.1'
}
group 'org.gradle.sample.plugin'
version '0.1'
repositories{
maven {
url "../repos/maven-repo"
}
jcenter()
}
To test the plugin, try to execute the plugin task testPlugin
> Task :testPlugin
custom plugin task executing.
Result: Stringtotest
Sorry to add this as an answer but I don't have enough points to comment (yes it is a bit late in coming but I found this in a search and it came so close, maybe this will help someone else).
The answer by #M.Ricciuti is correct, just missing one file, namely a settings.gradle in the referencing project (not the plugin) directory:
pluginManagement {
repositories {
maven {
url '../repos/maven-repo'
}
gradlePluginPortal()
ivy {
url '../repos/ivy-repo'
}
}
}
Many thanks, I have tried many things that didn't work before finding this, even the examples by gradle didn't work (or more likely I didn't run them correctly). Anyway I merged what I saw in the answers with M. Ricciuti's answer and saw that file in the sample.
My complete project is at https://github.com/reddierocket/sampleGradlePlugin
The readme has instructions to run it. (Note I did not include the wrapper but I am using gradle version 5.3.1.)

Protocol-Buffers: How to exclude code generation during build time in gradle?

We have a few .proto files from which java classes are generated.
Because we have to keep the generated files in the repository, we would like to generate them only when we want (and not during every single build ). We are using this plugin. Also we would like to stick with this plugin, since we have quite a few things configured and we found it pretty useful.
Is there a way to exclude code generation during build task in gradle?
You can enable/disable protobuf tasks based on the property passed via command line:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3'
}
}
apply plugin: 'java'
apply plugin: 'com.google.protobuf'
protobuf {
generateProtoTasks {
all().each { task ->
task.enabled = project.hasProperty('runProtobuf')
}
}
}
afterEvaluate {
println "generateProto enabled ${tasks.generateProto.enabled}"
println "generateTestProto enabled ${tasks.generateTestProto.enabled}"
}

Compiling GRPC server/client

I'm having a lot of trouble figuring out how to compile a GRPC Java server. I looked all over the grpc.io website and closest thing I found was this: http://www.grpc.io/docs/#quick-start , where I run
../gradlew -PskipCodegen=true installDist to build, and
./build/install/grpc-examples/bin/hello-world-client to run the client. This all works, but only for the hello-world tutorial. I have no idea how to do this for my own client/server. I'm able to generate the client/server protobufs using the .proto file. I looked in their readme and Java tutorial and couldn't find out how to compile the actual server (and client) after I write them
https://github.com/grpc/grpc-java/blob/master/examples/README.md
(can't link java tutorial because I dont have enough reputation). Unless there's documentation im missing, does anyone know how to compile a server and client that implements the GRPC classes generated from the .proto file? I did spend a fair amount of time searching. Any advice is much appreciated, thanks.
Also have a similar problem, ensure that:
You configured correctly the protoc, that will be downloading the executable and configure it as an environment variable of your OS.
The build.gradle file, make sure to include protobuf-gradle-plugin:
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'com.google.protobuf'
ext.grpcVersion = '1.0.1'
ext.protobufVersion = '3.0.2'
buildscript {
repositories { mavenCentral() }
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0' }
}
repositories {
mavenCentral()
}
dependencies {
compile "com.google.protobuf:protobuf-java:${protobufVersion}"
compile "io.grpc:grpc-all:${grpcVersion}"
}
protobuf {
protoc { artifact = "com.google.protobuf:protoc:${protobufVersion}" }
plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } }
generateProtoTasks { ofSourceSet('main')*.plugins { grpc { } } }
}
idea {
module {
sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java");
sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/grpc");
}
}
Your proto file:
syntax = "proto3";
package com.company.project;
service CompanyService{
rpc call(RequestMessage) returns (ResponseMessage) {}
}
Run gradle clean build, and it should generate your service and client classes for CompanyService.
The idea plugin, is jut for telling IntelliJ to recognize the src/main/proto as a source set.
To actually execute the client and server, you will need to make the implementation, mentioned in the tutorial for gRpc, and then apply the application plugin, in order to generate correctly the executable jar
//build.grdle code...
apply plugin: 'application'
mainClassName = 'com.company.project.MainClass'
jar { manifest { attributes('Main-Class' : mainClassName) } }
I had a similar issue but solved it using it in Gradle by adding the 'application' plugin. Before I was using the 'java' plugin and I could only generated a jar file. After switching to the 'application' plugin there is a gradle task similar to the gRPC example.
./gradlew installDist
And now to start your server you can run something similar to this:
./build/install/your-project/bin/your-server
To actually generate the Java classes off my .proto files I needed to run './gradle build' and also include the source generated using the sourceDir element you can see in the build.gradle below.
This is the full build.gradle file.
apply plugin: 'application'
apply plugin: 'com.google.protobuf'
apply plugin: 'idea'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.6'
}
}
repositories {
jcenter()
}
dependencies {
compile 'io.grpc:grpc-all:0.14.0'
}
mainClassName = "com.domain.service.YourMainClass"
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.0.0-beta-2"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:0.14.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
idea {
module {
sourceDirs += file("${projectDir}/build/generated/source/proto/main/grpc");
sourceDirs += file("${projectDir}/build/generated/source/proto/main/java");
}
}
I am new to gRPC so any improvments to my Gradle file would be appericated.
This question has been answered on groups.google.com by 'Eric Anderson':
The JAR only has your code in it. It sounds like you want to make a "fat" jar which includes all your dependencies. You can do something like this:
jar {
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
Note that that isn't gRPC-specific; it's just working with Gradle. There may be alternatives, such as a quick Googling returned gradle-fatjar-plugin.

Creating a Gradle Custom Plugin with Java

I'm creating a build process with Gradle and I want to provide a plugin that uses Java code. The Gradle plugin documentation says this is possible:
You can implement a custom plugin in any language you like, provided the implementation ends up compiled as bytecode. For the examples here, we are going to use Groovy as the implementation language. You could use Java or Scala instead, if you want.
However, after multiple hours of Googling and reading, I have yet to find any explanation of how to create a Gradle custom plugin with Java. It seems like you could create the code for it in a directory like:
<rootProjectDir>/buildSrc/src/main/java/
MyGradlePlugin.java
MyGradleTasks.java
But the question then becomes:
How to implement the plugin class and tasks in Java to be compatible with Gradle?
How to get Gradle to recognize the Java classes and tasks so you can use them in a build?
Can you just reference the plugin class like you do for the Groovy equivalent?
src/main/resources/META-INF/gradle-plugins/myjavaplugin.properties
implementation-class=org.me.MyGradlePlugin
I realize that I could just call the Java code with project.javaexec or JavaExec, but I'm concerned this will make my build process less portable.
Here's a basic, stand-alone, Java-based Gradle plugin and the steps to get it working:
Make sure Gradle 1.6 or higher and Java JDK is installed
Create these files below with the directory structure indicated
Change directories to the <projectRoot>/plugin directory
Execute the plugin build: $ gradle uploadArchives This (very important) step compiles the Java code and puts it in your local Maven repo (../repo).
Now execute the consumer script by changing directories to <projectRoot>/consumer
Execute the script that depends on the plugin: $ gradle checkitout
Java Classes
projectRoot/plugin/src/main/java/org/joefernandez/gradle/MyJavaPlugin.java
package org.joefernandez.gradle;
import org.gradle.api.Project;
import org.gradle.api.Plugin;
public class MyJavaPlugin implements Plugin<Project> {
#Override
public void apply(Project target) {
target.task("javaTask");
}
}
projectRoot/plugin/src/main/java/org/joefernandez/gradle/MyJavaTask.java
package org.joefernandez.gradle;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
public class MyJavaTask extends DefaultTask {
#TaskAction
public void javaTask() {
System.out.println("Hello from MyJavaTask");
}
}
Plugin Class declaration
projectRoot/plugin/src/main/resources/META-INF/gradle-plugins/test-plugin.properties
implementation-class=org.joefernandez.gradle.MyJavaPlugin
Plugin Build Script
Note the uploadArchives task: You must run this task to make the plugin available to the consumer script.
projectRoot/plugin/build.gradle
apply plugin: 'java'
dependencies {
compile gradleApi()
}
apply plugin: 'maven'
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.11'
}
group = 'org.joefernandez'
version = '1.0-SNAPSHOT'
uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('../repo'))
}
}
}
Settings for the Plugin
projectRoot/plugin/settings.gradle
rootProject.name = 'MyJavaPlugin'
Root script
projectRoot/build.gradle
apply plugin: 'java'
dependencies {
compile gradleApi()
}
Consumer script
projectRoot/consumer/build.gradle
buildscript {
repositories {
maven {
url uri('../repo')
}
}
dependencies {
classpath group: 'org.joefernandez',
name: 'MyJavaPlugin',
version: '1.0-SNAPSHOT'
}
}
apply plugin: 'test-plugin'
task checkitout(type: org.joefernandez.gradle.MyJavaTask) {
println("running consumer task!")
}
I would like to propose a few amendments to Joe's great answer.
projectRoot/plugin/src/main/java/org/joefernandez/gradle/MyJavaPlugin.java
This change wires the task into the supplied project without the need to sub-class it.
package org.joefernandez.gradle;
import org.gradle.api.Project;
import org.gradle.api.Plugin;
public class MyJavaPlugin implements Plugin<Project> {
#Override
public void apply(Project target) {
// CHANGE HERE
target.getTasks().create("javaTask", MyJavaTask.class);
}
}
Consumer script
projectRoot/consumer/build.gradle
This change removes the now unnecessary task definition
buildscript {
repositories {
maven {
url uri('../repo')
}
}
dependencies {
classpath group: 'org.joefernandez',
name: 'MyJavaPlugin',
version: '1.0-SNAPSHOT'
}
}
apply plugin: 'test-plugin'
// CHANGE HERE
This them changes step 6, to:
Execute the script that depends on the plugin: $ gradle javaTask
Plugin classes must implement the org.gradle.api.Plugin interface. Task classes typically extend the org.gradle.api.DefaultTask class. It doesn't matter which (JVM) language is used for this. The Gradle codebase contains many plugin and task classes implemented in Java.
How to build and ship a plugin is another question, again mostly unrelated to which language is used. See the Gradle User Guide and samples/customPlugin in the full Gradle distribution.

Categories