This project requires JVM version of at least 1.7
Table of Contents top
- Table of Contents
- javaSample
- Initial Build
- The Source Files
- Adding in the extension
- Updating Versions - Catch-22
- WARNING ABOUT DAEMON MODE
- Publishing the Plugin
- Creating a new plugin
- Building the Package
- Running the Tests
javaSample top
An example gradle plugin written in Java
Initial Build top
The first thing that is going to happen when you try to build the project is that it is going to fail:
gradle build
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring root project 'javaSample'.
> Could not resolve all dependencies for configuration ':classpath'.
> Could not find synapticloop:javaSample:1.0.0.
Searched in the following locations:
file:/Users/synapticloop/.m2/repository/synapticloop/javaSample/1.0.0/javaSample-1.0.0.pom
file:/Users/synapticloop/.m2/repository/synapticloop/javaSample/1.0.0/javaSample-1.0.0.jar
https://plugins.gradle.org/synapticloop/javaSample/1.0.0/javaSample-1.0.0.pom
https://plugins.gradle.org/synapticloop/javaSample/1.0.0/javaSample-1.0.0.jar
https://plugins.gradle.org/m2/synapticloop/javaSample/1.0.0/javaSample-1.0.0.pom
https://plugins.gradle.org/m2/synapticloop/javaSample/1.0.0/javaSample-1.0.0.jar
Required by:
:javaSample:unspecified
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 2.429 secs
This is due to the fact that it cannot find the plugin, since you haven't built the plugin yet, so it is expecting the dependency which hasn't been built, to exist before it can build the extension - kind of a catch-22 situation.
you need to do this:
gradle -b build-initial.gradle build pTML
the pTML
above is a short form of publishToMavenLocal
, so you could also have done:
gradle -b build-initial.gradle build publishToMavenLocal
This will publish the plugin to maven local, which means that you can now do a:
gradle build
The Source Files top
Here is a list of the within this project
├── .gitignore // this is git ignore file - generated from https://www.gitignore.io/api/gradle,eclipse,java
├── build-initial.gradle // this is the initial build file - invoked by gradle -b build-initial build pTML
├── build.gradle // the main build.gradle file
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew // gradle invoker script
├── gradlew.bat // windows gradle invoker script
├── settings.gradle // settings for the gradle build
└── src
├── docs
│ └── first-build.md // documentation
├── main
│ ├── java
│ │ └── synapticloop
│ │ └── gradle
│ │ └── plugin
│ │ ├── JavaSampleGoodbyeTask.java // the goodbye task
│ │ ├── JavaSampleHelloTask.java // the hello task
│ │ ├── JavaSamplePlugin.java // the plugin registration
│ │ └── JavaSamplePluginExtension.java // the extension point for configuration
│ └── resources
│ └── META-INF
│ └── gradle-plugins
│ └── synapticloop.javaSample.properties // the properties file to register the plugin
└── test
└── java
Adding in the extension top
The extension allows the user of your plugin to set or over-ride defaults. You should always set sensible defaults for all options.
Updating Versions - Catch-22 top
There is a little bit of back and forth with the plugin development. For example if you wish to update the version, you will need to build the version first, then update the registration, then run the plugin. E.g updating to version 1.0.1.
Step 1 - update the build version number top
in the build.gradle
file - the lines
// textual information for this project
group = 'synapticloop'
archivesBaseName = 'javaSample'
description = """An example gradle plugin written in Java"""
version = '1.0.0'
change the version = '1.0.0'
to version = '1.0.1'
Step 2 - build and publish the new version locally top
gradle build pTML
Step 3 - update the included plugin version top
then in the build.gradle
file:
buildscript {
repositories {
mavenLocal()
maven {
url "https://plugins.gradle.org/"
}
}
dependencies {
classpath 'synapticloop:javaSample:1.0.0'
}
}
change the line classpath 'synapticloop:javaSample:1.0.0'
to classpath 'synapticloop:javaSample:1.0.1'
and you may then invoke the task with the updated version number.
Step 4 - invoke the new task top
gradle javaSampleHello
WARNING ABOUT DAEMON MODE top
Since gradle caches the plugin - it is best to NOT use --daemon
in your
build file if you do not update the plugin version number.
Gradle 3.0+ top
From Gradle 3.0 onwards, --daemon
is defaulted to be on all of the time, you
need to disable the daemon (see https://docs.gradle.org/current/userguide/gradle_daemon.html#sec:disabling_the_daemon) for instructions on how to disable it.
In a nutshell, there are two ways to disable the daemon:
- Via environment variables: add the flag
-Dorg.gradle.daemon=false
to theGRADLE_OPTS
environment variable - Via properties file: add
org.gradle.daemon=false
to the«GRADLE_USER_HOME»/gradle.properties
file
Publishing the Plugin top
Step 1 - Register your plugin group top
Go to https://login.gradle.org/user/register and fill in the details:
NOTE: Your username will become the group - i.e. if your username is
synapticloop
then your plugins will be registered under thesynapticloop
group and will reside here https://plugins.gradle.org/u/synapticloop.
Step 2 - Get your API key top
Click on the API Keys
link in the tabbed section, which will list your api keys:
gradle.publish.key=SOMETHING
gradle.publish.secret=SOMETHING_SECRET
Copy them to your HOME_DIR/.gradle/gradle.properties (~/.gradle/gradle.properties) file:
Step 3 - install the gradle plugin publishing plugin top
In your build.gradle
file in the plugins
section, make sure you have included
the com.gradle.plugin-publish
plugin:
// list all of the plugins for this project
plugins {
...
id 'com.gradle.plugin-publish' version '0.9.3'
...
}
Step 4 - Set up the plugin publishing task top
Include all of the following in your build.gradle
file
/**
* Below is everything that you need to publish your plugin
*/
// The fatJar tasks assembles all of the output files (compiled java, properties
// etc.) into a single jar
task fatJar(type: Jar) {
classifier = 'all'
from(sourceSets.main.output) { include "**" }
}
// we want to ensure that the fatJar task is run
build.finalizedBy(project.tasks.fatJar)
publishPlugins.finalizedBy(project.tasks.fatJar)
// links to javadoc - the javadoc task is needed for the maven publication, not
// for the publishing of plugins
def javaApiUrl = 'http://docs.oracle.com/javase/1.7.0/docs/api/'
def groovyApiUrl = 'http://groovy.codehaus.org/gapi/'
tasks.withType(Javadoc) {
options.links(javaApiUrl, groovyApiUrl)
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from 'build/docs/javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
publishing {
publications {
Synapticloop(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
groupId group
artifactId archivesBaseName
pom.withXml {
configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
asNode().dependencies[0].dependency.find {
it.artifactId[0].text() == dep.moduleName &&
it.groupId[0].text() == dep.moduleGroup
}.scope[0].value = 'compile'
}
}
}
}
}
// Now it is time to publish the plugin
pluginBundle {
website = 'https://github.com/synapticloopltd/gradle-plugin-java-sample'
vcsUrl = 'https://github.com/synapticloopltd/gradle-plugin-java-sample'
description = 'A sample gradle plugin built with java'
tags = [ 'sample' ]
plugins {
gradlePluginJava {
id = 'synapticloop.javaSample'
displayName = 'Synapticloop sample Gradle plugin in Java'
}
}
}
You can now publish your plugin with a simple:
gradle publishPlugin
or more concisely:
gradle pP
Creating a new plugin top
Required Information top
- plugin group - referred to as
«PLUGIN_GROUP»
- plugin description = referred to as
«PLUGIN_DESCRIPTION»
- plugin name - referred to as
«PLUGIN_NAME»
- plugin package - referred to as
«PLUGIN.PACKAGE»
- plugin path - referred to as
«PLUGIN_PATH»
- this should match the plugin package as per java conventions
Step 1 - create the .properties
file top
Create a file located at:
src/main/resources/META-INF/«PLUGIN_GROUP».«PLUGIN_NAME».properties
Enter the following details:
implementation-class=«PLUGIN_GROUP».«PLUGIN_NAME»Plugin
Step 2 - create the Plugin.java
file top
Create a file located at:
src/main/java/«PLUGIN_PATH»/«PLUGIN_NAME»Plugin.java
This MUST match the implementation-class
listed as per Step 1
The file should contain the following
package «PLUGIN.PACKAGE»;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class «PLUGIN_NAME»Plugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getExtensions().create("«PLUGIN_NAME»", «PLUGIN_NAME»PluginExtension.class);
project.getTasks().create("«PLUGIN_TASK_NAME»", «PLUGIN_NAME»Task.class);
}
}
Step 3 - create the PluginExtension.java
file top
Create a file located at:
src/main/java/«PLUGIN_PATH»/«PLUGIN_NAME»PluginExtension.java
The file should contain the following:
package «PLUGIN.PACKAGE»;
public class «PLUGIN_NAME»PluginExtension {
// here you can put your member variables
// don't forget to create getters/setters for all of the member variables
}
Step 4 - create the Task.java
file top
Create a file located at:
src/main/java/«PLUGIN_PATH»/«PLUGIN_NAME»Task.java
The file should contain the following:
package «PLUGIN.PACKAGE»;
import org.gradle.api.DefaultTask;
import org.gradle.api.logging.Logger;
import org.gradle.api.tasks.TaskAction;
public class «PLUGIN_NAME»Task extends DefaultTask {
private Logger logger;
private «PLUGIN_NAME»PluginExtension extension;
public JavaSampleHelloTask() {
setGroup("«PLUGIN_GROUP»");
setDescription("«PLUGIN_DESCRIPTION»");
this.logger = getProject().getLogger();
}
@TaskAction
public void generate() {
extension = getProject().getExtensions().findByType(«PLUGIN_NAME»PluginExtension.class);
if (extension == null) {
extension = new «PLUGIN_NAME»Extension();
}
logger.info("Logging something, this will only be seen if the gradle task is invoked with --info");
}
}
Step 5 - create the build-initial.gradle
file top
Use the ./build-initial.gradle
file as a starting point, you will need to
update the following values:
// textual information for this project
group = '«PLUGIN_ARTEFACT_BASE»'
archivesBaseName = '«PLUGIN_NAME»'
description = """«PLUGIN_DESCRIPTION»"""
version = '1.0.0'
Step 6 - create the build.gradle
file top
Use the ./build.gradle
file as a starting point, you will need to
update the values in the file as per step 5 above.
Building the Package top
*NIX/Mac OS X top
From the root of the project, simply run
./gradlew build
Windows top
./gradlew.bat build
This will compile and assemble the artefacts into the build/libs/
directory.
Note that this may also run tests (if applicable see the Testing notes)
Running the Tests top
*NIX/Mac OS X top
From the root of the project, simply run
gradle --info test
if you do not have gradle installed, try:
gradlew --info test
Windows top
From the root of the project, simply run
gradle --info test
if you do not have gradle installed, try:
./gradlew.bat --info test
The --info
switch will also output logging for the tests
Dependencies - Gradle top
dependencies {
runtime(group: 'synapticloop', name: 'javaSample', version: '1.0.0', ext: 'jar')
compile(group: 'synapticloop', name: 'javaSample', version: '1.0.0', ext: 'jar')
}
or, more simply for versions of gradle greater than 2.1
dependencies {
runtime 'synapticloop:javaSample:1.0.0'
compile 'synapticloop:javaSample:1.0.0'
}
Dependencies - Maven top
<dependency>
<groupId>synapticloop</groupId>
<artifactId>javaSample</artifactId>
<version>1.0.0</version>
<type>jar</type>
</dependency>
Dependencies - Downloads top
You will also need to download the following dependencies:
NOTE: You may need to download any dependencies of the above dependencies in turn (i.e. the transitive dependencies)
--
This README.md file was hand-crafted with care utilising synapticloop
templar
->
documentr
--