martes, 2 de agosto de 2022
Gradle-7 (14) Gradle Draft(2). Multiproject
1. Defining layers
Common layers are:
1. User Interface (UI) that can contain HTML, javascript, and CSS files
2. API or server-side application responding HTTP request (java)
3. Database connection (DB layer) consumed by the API layer (java)
1. User Interface (UI) that can contain HTML, javascript, and CSS files
2. API or server-side application responding HTTP request (java)
3. Database connection (DB layer) consumed by the API layer (java)
2. Create a Multiproject
Eclipse:
"File-> New -> Gradle -> Gradle Project"
Select java version 15 or below, and maven 7.5
Gradle:
gradle init
Type of project: 2. Application
Language: 3. Java
Split functionality: 1. no
Script DSL: 1.Groovy
Test framework: 4. JUnit Jupiter
Project name: (the name of the folder)
Source package: (any name)
gradle init
Type of project: 2. Application
Language: 3. Java
Split functionality: 1. no
Script DSL: 1.Groovy
Test framework: 4. JUnit Jupiter
Project name: (the name of the folder)
Source package: (any name)
settings.gradle file content:
rootProjectName= 'your-project-name'
include ('app') // in gradle or include ('lib') in Eclipse creation
Show projects:
./gradlew projects
Create a subproject
-Add the new project reference in settings.gradle
include ('app', 'newProject')
or without parentheses
include 'app', 'newProject'
or separating lines
include 'app'
include 'newProject'
-Add a subfolder (newProject) that will contain the project and add the build.gradle and the src/main/java and other folder needed by a standard java project
-Adding a dependency on another project
dependency {
implementation project(':app')
}
3. The copy and zip tasks
NOTE: Gradle uses routes relative to the directory where the build.path is
1. Copying one directory:
tasks.register('copyDescription', Copy) {
from 'descriptions' //directory
into "$buildDir/descriptions"
}
2. Copying one file:
tasks.register('copyDescription', Copy) {
from file 'descriptions/myFile.txt'
into "$buildDir/descriptions"
}
3. Copying one file into a directory and create it:
tasks.register('copyDescription', Copy) {
from file 'descriptions/myFile.txt'
into layout.buildDirectory.dir('descriptions')
}
4. Copying multiple files with pattern:
tasks.register('copyDescription', Copy) {
from fileTree(layout.projectDirectory)
include 'descriptions/**'
into "$buildDir/descriptions"
}
5. Copying multiple files with pattern but REMOVING directory structure:
tasks.register('copyDescription', Copy) {
from fileTree(layout.projectDirectory) {
include 'description/**'
}.files
into layout.buildDirectory.dir('descriptions')
}
5. Copying multiple files to ZIP
tasks.register('copyDescription', Copy) {
from 'descriptions'
into "$buildDir/descriptions"
}
tasks.register('zipDescription', Zip) {
from copyDescription // files resulting from copyDescription task
destinationDirectory buildDir
from 'descriptions.zip'
}
6. Copying multiple files to ZIP to another directory
tasks.register('zipDescription', Zip) {
from copyDescription // files resulting from copyDescription task
destinationDirectory layout.buildDirectory.dir('myZipDirectory')
// or destinationDirectory = file ("$buildDir/myZipDirectory")
from 'descriptions.zip'
}
4. "buildScr" and convention plugins
buildSrc applies the "build.gradle" logic to multiple projects, using convention plugins (it is similar to "include" in C). Eclipse can be very tricky and maybe gets into errors
Create a project with Gradle:
gradle init
Type of project: 2. Application
Language: 3. Java
Split functionality: 2. yes
Script DSL: 1.Groovy
Test framework: 4. JUnit Jupiter
Project name: (the name of the folder)
Source package: (any name)
gradle init
Type of project: 2. Application
Language: 3. Java
Split functionality: 2. yes
Script DSL: 1.Groovy
Test framework: 4. JUnit Jupiter
Project name: (the name of the folder)
Source package: (any name)
The project structure is:
The build.gradle in the buildSrc folder is:
plugins {
// Support convention plugins written in Groovy. Convention plugins are build scripts
// in 'src/main' that automatically become available as plugins in the main build.
id 'groovy-gradle-plugin'
}
repositories {
// Use the plugin portal to apply community plugins in convention plugins.
gradlePluginPortal()
}
And the ·.gradle" files in the "buildScr/src/main/groovy" are:
lesson08.java-common-conventions.gradle:
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
constraints {
implementation 'org.apache.commons:commons-text:1.9'
}
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
}
tasks.named('test') {
useJUnitPlatform()
}
lesson08.java-library-conventions.gradle:
plugins {
// Apply the common convention plugin for shared build configuration between
// library and application projects.
id 'lesson08.java-common-conventions'
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
}
lesson08.java-application-conventions.gradle:
plugins {
// Apply the common convention plugin for shared build configuration between
// library and application projects.
id 'lesson08.java-common-conventions'
// Apply the aplication plugin to add support for building a CLI application in Java
id 'application'
}
5. Create custon tags
These are the steps:
1. Can define tasks class in build.gradle
2. must extend DefaultTask
3. add a @TaskAction method
4. extract configuration properties into methods
5. return Property<T> (or class that extends this)
6. have @Input type annotation
7. move task class to buildSrc for reuse
5.1 Create the task FileDiffTask in the build.gradle file
In this example, it is compared the size of a file given by param with a fixed file:
This code is added to the build.gradle:
//Define the type of the action
abstract class FileDiffTask extends DefaultTask {
@InputFile //Define input parameter of type file
abstract RegularFileProperty getFile1() //Define property file1
@TaskAction //Define the action of the task
def diff() {
//Fixed file
File file2 = project.file('src/main/resources/static/images/logflume.jpg')
if (file1.get().asFile.size() == file2.size()) {
println "${file1.get().asFile.name} and {file2.name} have the same size"
}else if (file1.size() > file2.size()) {
println "${file1.get().asFile.name} was larger"
}else {
println "{file2.name} was larger"
}
}
}
//Create an instance of the task
task.register('fileDiff', FileDiffTask) {
file1 = file('src/main/resources/static/images/rollercoaster.jpg')
}
5.2 Inserting the logic in the buildSrc folder
1. Create a package in the buildSrc/src/main/groovy folder (e.g. "com.ximo")
2. Add a Groovy class with the same name as the task (FileDiffTask)
3. Add the import declaration at the top of the file of this Groovy class
import org.gradle.api.tasks.TaskAction
3. Copy the previous code of the definition of the class (not the "tasks.register" part )
4. In the build.gradle of the project (not the buildSrc) file remove the definition of the class (as now it is copied to the Groovy class in the buildSrc folder) and add the import declaration
import com.ximo.FileDiffTask
5. Now the file build.gradle is as follows
import com.ximo.FileDiffTask
plugins {
id 'java-library'
}
//Create an instance of the task
task.register('fileDiff', FileDiffTask) {
file1 = file('src/main/resources/static/images/rollercoaster.jpg')
}
6. Now execute the task as ./gradlew fileDiff
6. Create custom plugin
These are the steps:
1. A plugin can contain tasks
2. implements "Plugin" interface
3. use "apply pluggin: <name> " for "inline" plugins
4. use "extensions" for configuring the plugin
5. create "extension class" and a "named instance".
6.1 Create the plugin FileDiffPlugin in the build.gradle file
import com.ximo.FileDiffTask //References the task to assign to the plugin
plugins {
id 'java-library'
}
//Define the extension the plugin with the parameter to use (file1)
abstract class FileDiffPluginExtension {
abstract Regular Property getFile1() //parameter "file1"
}
// Define the value of parameter "file1"
fileDiff {
file1 = file('src/main/resources/static/images/rollercoaster.jpg')
}
//Define the class of the plugin
class FileDiffPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
//Adds the extension
def extension = project.extensions.create('fileDiff', FileDiffPluginExtension)
//Adds the task with the parameter
project.tasks.register('fileDiff', FileDiffTask) {
file1 = extension.file1 //indicated in fileDiff
}
}
}
// Apply the plugin
apply plugin: FileFiffPlugin
Now execute the task as ./gradlew fileDiff
6.2 Inserting the logic in Maven
Note that the plugin consists of 3 classes (Plugin class itself, Extensions and Tasks classes)
1. Create a gradle project (create folder ->gradle init->1.basic -> 1.Groovy -> default no -> default)
2. In the build.gradle:
plugins {
id 'groovy-gradle-plugin' // the same as convention plugins
id 'maven-publish' // for publishing in maven
}
// for publishing in gradle we need a group and version
group = 'com.ximo'
version = '0.1.0-SNAPSHOT''
gradlePlugin {
plugins {
fileDiff {
id = 'com.ximo.file-diff' // unique name
implementationClass 'com.gradlehero.FileDiffPlugin'
}
}
}
3. Create folder src/main/groovy/com/ximo
4. Create groovy classes for plugins, extensions and tasks
5. FileDiffPlugin.groovy (plugin class)
package com.ximo
import org.gradle.api.Plugin
import org.gradle.api.Project
//Define the class of the plugin
class FileDiffPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
//Adds the extension
def extension = project.extensions.create('fileDiff', FileDiffPluginExtension)
//Adds the task with the parameter
project.tasks.register('fileDiff', FileDiffTask) {
file1 = extension.file1 //indicated in fileDiff
}
}
}
6. FileDiffTask.groovy (extension class)
package com.ximo
import org.gradle.api.Plugin
//Define the extension the plugin with the parameter to use (file1)
abstract class FileDiffPluginExtension {
abstract Regular Property getFile1() //parameter "file1"
}
7. FileDiffTask.groovy (task class)
package com.ximo
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.InputFile
import org.gradle.api.TaskAction
//Define the type of the action
abstract class FileDiffTask extends DefaultTask {
@InputFile //Define input parameter of type file
abstract RegularFileProperty getFile1() //Define property file1
@TaskAction //Define the action of the task
def diff() {
//Fixed file
File file2 = project.file('src/main/resources/static/images/logflume.jpg')
if (file1.get().asFile.size() == file2.size()) {
println "${file1.get().asFile.name} and {file2.name} have the same size"
}else if (file1.size() > file2.size()) {
println "${file1.get().asFile.name} was larger"
}else {
println "{file2.name} was larger"
}
}
}
8. Now we can build ẁith ./gradlew build
9. Now we can publish ẁith ./gradlew publishToMavenLocal
10. To use this plugin in a project, the repository must be indicated in the settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
mavenLocal()
}
}
rootProject.name='theme-park-manager'
include 'api', 'service', 'ui'
7. Test custom plugin (Spock framework)
Use the Spock framework with an expressive Groovy test
Use "GradleTestKit" for plugin functional test
In the "given:" section, create build file
in the "when:" section use "GradleRunner" to execute build
In the "then:" section verify expectation.
This Tom Gregory link is the source code
The file build.gradle
plugins { id 'groovy-gradle-plugin' id 'maven-publish' } group = 'com.gradlehero' version = '0.1.0-SNAPSHOT' repositories { mavenCentral() } dependencies { testImplementation 'org.spockframework:spock-core:2.0-groovy-3.0' } test { useJUnitPlatform() } gradlePlugin { plugins { fileDiff { id = 'com.gradlehero.file-diff' implementationClass = 'com.gradlehero.FileDiffPlugin' } } }
The file test/groovy/com/gradlehero/FileDiff/PluginFunctionalTest.groovy
package com.gradlehero import org.gradle.testkit.runner.GradleRunner import spock.lang.Specification import spock.lang.TempDir import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class FileDiffPluginFunctionalTest extends Specification { @TempDir File testProjectDir File testFile1 File testFile2 File buildFile def setup() { testFile1 = new File(testProjectDir, 'testFile1.txt') testFile2 = new File(testProjectDir, 'testFile2.txt') buildFile = new File(testProjectDir, 'build.gradle') buildFile << """ plugins { id 'com.gradlehero.file-diff' } fileDiff { file1 = file('${testFile1.getName()}') file2 = file('${testFile2.getName()}') } """ } def "can diff 2 files of same length"() { given: testFile1.createNewFile() testFile2.createNewFile() when: def result = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments('fileDiff') .withPluginClasspath() .build() then: result.output.contains('testFile1.txt and testFile2.txt have the same size') result.task(':fileDiff').outcome == SUCCESS } def "can diff 2 files where 1st file larger than 2nd"() { given: testFile1 << 'Some text' testFile2.createNewFile() when: def result = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments('fileDiff') .withPluginClasspath() .build() then: result.output.contains('testFile1.txt was larger') result.task(':fileDiff').outcome == SUCCESS } def "can diff 2 files where 2nd file larger than 1st"() { given: testFile1.createNewFile() testFile2 << 'Some text' when: def result = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments('fileDiff') .withPluginClasspath() .build() then: result.output.contains('testFile2.txt was larger') result.task(':fileDiff').outcome == SUCCESS } }
Suscribirse a:
Entradas
(
Atom
)